這道題目狀態轉移方程比較複雜,剛開始以為沒這麼多情況,看了好多大牛的部落格再加上與同學討論才看懂,寫下心得。
因為起點不固定,所以我們乙個乙個來考慮,先從角上考慮,設三個陣列來表示分別為d,a,sum,分別表示為「從乙個角開始然後回到同一列的對應位置的總個數」, 「從乙個角開始的總個數(包括回到對應位置和不回到對應位置)」, 「表示總的個數」
1. 當回到對應位置時:
d[1] = 1,d[n] = 2 * d[n-1];
因為他可以有兩種方式出去,最後再回來,如圖(a), 圖上是以右上角這個格仔出發的,然後回到右下角這個格仔,一共有兩種方式出去。
2. 不一定回到對應位置時,就是乙個角的總個數:
a[n] = d[n] + 2*a[n - 1] + 4 * a[n - 2];
其中, d[n]表示回到對應位置的,而a[n-1]這種情況如圖(b)所示,先上對面去,然後再接著向前走,所以還是兩種方式出去,後面這種表示挨著走完兩列,就是前面沒有的這種情況,一共有兩種走法,但是每種走法又有兩種出去的方式,所以是4種,如下圖(c)表示的,黑色(1,2兩種)的和紅色的(3,4兩種)箭頭方向。
這只是其中乙個角,因為只要n>2就有4個角,所以這個所有角的個數就是4*a[n];
3.當從中間位置開始走時:
假設從 i 開始走, 2*(2*d[i-1]*2*a[n-i] + 2*d[n-i]*2*a[i-1]),最後從2 - n-1 遍歷一遍加起來
假設從 i 開始走,顯然不能直接往下走,否則無法遍歷所有點,應當是先遍歷左邊(右邊)所有點,然後回到相對的點,然後遍歷右邊(左邊)的點。注意先遍歷的時候,必須是採用「遍歷全體格仔後回到與之相對的格仔」的走法,否則無法遍歷出發點正下方的點,而後遍歷則不受限制。所以先往左走的 i 之前的方法總數就是d[i - 1], 之後a[n - i],同理可以推先往右走的。
附ac**:
1 #include 2 #include 3view codeusing
namespace
std;
4const
int n = 1005;5
const
long
long mod = 1000000007;6
long
long d[n], a[n], sum[n];//
d陣列表示從乙個角出發,最後回到出發點的同一列所對應的那個格仔的總個數,7//
a陣列表示所有乙個角出發的總個數,sum表示總的個數
8int
main()925
intn;
26while (cin >>n)
2730
31return0;
32 }
nyoj 980 格仔刷油漆
時間限制 1000 ms 記憶體限制 65535 kb 難度 3 描述 x國的一段古城牆的頂端可以看成 2 n個格仔組成的矩形 如下圖所示 現需要把這些格仔刷上保護漆。你可以從任意乙個格仔刷起,刷完一格,可以移動到和它相鄰的格仔 對角相鄰也算數 但不能移動到較遠的格仔 因為油漆未乾不能踩!比如 a ...
1347 例4 8 格仔遊戲
alice和bob玩了乙個古老的遊戲 首先畫乙個n n的點陣 下圖n 3 接著,他們兩個輪流在相鄰的點之間畫上紅邊和藍邊 直到圍成乙個封閉的圈 面積不必為1 為止,封圈 的那個人就是贏家。因為棋盤實在是太大了 n 200 他們的遊戲實在是太長了!他們甚至在遊戲中都不知道誰贏得了遊戲。於是請你寫乙個程...
2013 格仔刷油漆 dp
a表示在2 n的格仔,從四個頂點中任意乙個格仔出發遍歷全部格仔的種類數,a 1 1a 2 6 畫出所有情況 b表示在2 n的格仔,從任意乙個格仔出發,遍歷所有格仔且終點在出發點這一列,以為要回來,所有每一步只能一直往左或者右走 這樣該列另乙個格仔就會留個回來時刷 所以每一步2中選擇,b i 2 b ...