1580 鋪管道
codeforces
基準時間限制:1.5 秒 空間限制:131072 kb 分值: 40
難度:4級演算法題
現在要在乙個城市中鋪設管道。
這個城市是由 n×m 小方格組成的。每乙個小方格要麼是空的(管道可以鋪設在上面),要麼是實的(管道不能鋪在上面)。空的用』.』表示,實的用』#』表示。
管道鋪設的規則如下:
· 整條管道是形狀是寬度為1的折線;
· 管道只能鋪設在空的格仔上面;
· 管道的兩個端點只能在邊緣上,但是不能在角上;
· 管道最多只能轉兩個彎(90度);
· 在管道上的格仔有且只能有兩個是在邊緣上的;
· 如果管道是一條直線,那麼他的兩個端點必須是落在不同的邊上;
· 對於管道上的非邊緣格仔,每乙個格仔會有且僅有兩個相鄰的其它格仔在管道上;
· 對於管道上處於邊緣的格仔,僅有乙個相鄰的格仔處於管道上。
下面有一些合法的管道鋪設例子:
1
2
3
4
5
....#
....#
.*..#
*****
****..
***.
..# ..
..# *
...#
*.
# ...# #
..*# #
..*#
.....
...*
....*.
下面是一些非法鋪設的例子:
1
2
3
4
5
.**.#
*...#
.*.*#
.....
****..
*.*.
..# ..
..# *..
*# *.
# ...# #
..*# #
*.*#
.....
...*..
***.
這些例子中管道用』*』表示。
現在給定城市的地圖,請計算一下有多少種方法鋪設管道。
樣例解釋:
在這個樣例中,有三種方法鋪設管道(管道用'*'表示)。
1input2
3
.*..*
....
.*#
**#
**#.*.
....*.
單組測試資料。output第一行有兩個整數 n,m (2≤n,m≤2000),表示城市地圖的高和寬。
接下來n行,每一行有m個字母,表示城市地圖。
如果字元是』.』,表示該格仔是空的,管道可以鋪設。
如果字元是』#』,表示該格仔是實的,管道不能鋪設。
輸出乙個整數,表示管道鋪設方案的種數。input示例
樣例輸入1output示例3 3...
..#...
樣例輸出1system message3
(題目提供者)
visual c++的執行時限為:1500 ms ,空間限制為:131072 kb
示例及語言說明請按這裡
允許其他 ac 的使用者檢視此**,分享**才能檢視別人的**並有機會獲得勳章
題意很繁瑣,問題就是求滿足題目描述的管道數量。一開始想的廣搜,果斷超時。。但是好像cf不會超時啊。
後來查了發正解,發現問題可以轉化為折線問題。我們可以把管道看做折線(其實沒啥區別)
然後滿足題意的折線無非4種。。借鑑乙個大佬的圖。。
然後我們就可以按照題目要求查詢滿足要求的直線了,為哦了避免重複計算,所以考慮先計算縱向的
然後摺疊矩陣,交換位置(可能說的不是很對,詞窮了),中間的細節很多,敲了半天一直wa。
然後借鑑了一位大佬的**:才避免了許多重複計算。很巧妙
#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;
typedef long long ll;
#define inf 1000000000
#define mod 1000000007
#define maxn 2005
#define pi 3.1415926
#define lowbit(x) (x&-x)
#define eps 1e-9
char s[maxn];
bool a[maxn][maxn], b[maxn][maxn], c[maxn][maxn], d[maxn][maxn];
ll ans;
void solve(int n, int m, int flag)
ans += ((!c[i][j]) + (!d[i][j]))*tmp;
ans += ((!c[i][j] && !d[i][j - 1]) + (!c[i][j - 1] && !d[i][j]));
tmp += (!c[i][j - 1]) + (!d[i][j - 1]);//之後累加能組成下...右...上和上...右...下等折線
} if (!a[i][m] && flag)//加上從前邊任何一列開始為下...右...和上...右...的折線
ans += tmp + (!c[i][m - 1]) + (!d[i][m - 1]);//以及左右直達的直線
} if (flag)//在算其他型別折線的同事橫向直線順帶求出了,故直線只用再求一次 }
int main(void)
solve(n, m, 1);
for (i = 1;i <= n;i++)
for (j = 1;j <= m;j++)
b[j][i] = a[i][j];
memset(a, 0, sizeof(a));
for (i = 1;i <= m;i++)
for (j = 1;j <= n;j++)
a[i][j] = b[i][j];
solve(m, n, 0);
printf("%lld\n", ans);
return 0;
}
51nod 貪心入門
有若干個活動,第i個開始時間和結束時間是 si,fi 活動之間不能交疊,要把活動都安排完,至少需要幾個教室?分析 能否按照之一問題的解法,每個教室安排盡可能多的活動,即按結束時間排序,再貪心選擇不衝突的活動,安排乙個教室之後,剩餘的活動再分配乙個教室,繼續貪心選擇 反例 a 1,2 b 1,4 c ...
51nod 迷宮問題
1459 迷宮遊戲 基準時間限制 1 秒 空間限制 131072 kb 分值 0 難度 基礎題 你來到乙個迷宮前。該迷宮由若干個房間組成,每個房間都有乙個得分,第一次進入這個房間,你就可以得到這個分數。還有若干雙向道路鏈結這些房間,你沿著這些道路從乙個房間走到另外乙個房間需要一些時間。遊戲規定了你的...
51nod 硬幣遊戲
有乙個簡單但是很有趣的遊戲。在這個遊戲中有乙個硬幣還有一張桌子,這張桌子上有很多平行線 如下圖所示 兩條相鄰平行線之間的距離是1,硬幣的半徑是r,然後我們來拋硬幣到桌子上,拋下之後硬幣有時候會和一些直線相交 相切的情況也算是相交 有時候不會。請你來計算一下拋一次硬幣之後,該硬幣和直線相交數目的期望。...