【HDU - 5965】扫雷(dp)
題干:
掃雷游戲是晨晨和小璐特別喜歡的智力游戲,她倆最近沉迷其中無法自拔。
該游戲的界面是一個矩陣,矩陣中有些格子中有一個地雷,其余格子中沒有地雷。 游戲中,格子可能處于己知和未知的狀態。如果一個己知的格子中沒有地雷,那么該 格子上會寫有一個一位數,表示與這個格子八連通相鄰的格子中地雷總的數量。
現在,晨晨和小璐在一個3行N列(均從1開始用連續正整數編號)的矩陣中進 行游戲,在這個矩陣中,第2行的格子全部是己知的,并且其中均沒有地雷;而另外 兩行中是未知的,并且其中的地雷總數量也是未知的。
晨晨和小璐想知道,第1行和第3行有多少種合法的埋放地雷的方案。
Input
包含多組測試數據,第一行一個正整數T,表示數據組數。
每組數據由一行僅由數字組成的長度為N的非空字符串組成,表示矩陣有3行N 列,字符串的第i個數字字符表示矩陣中第2行第i個格子中的數字。
保證字符串長度N <= 10000,數據組數<= 100。
Output
每行僅一個數字,表示安放地雷的方案數mod100,000,007的結果。
Sample Input
2 22 000Sample Output
6 1解題報告:
直接dp[n][3][3],dp[i][j][k]代表第i列放置了j個地雷,第i-1列放置k個地雷的前綴合法方案數。更新的時候直接更新到第n+1列,這樣就不用特判了。直接取值就行。注意注釋掉的那一句,不需要特判,當時是想的,剩下那些狀態都是非法的了,所以不需要進行更新了,但是其實更新了也沒關系,因為反正也用不到,也就是說你可以更新了,但是不取這個值就可以了。
再就是數組需要開到dp[n][9][9],因為雖然你用不到這些值,但是你狀態轉移方程中可能會用到這些非法值,所以為了防止越界,需要數組開大一點。(當然,你直接用ifelse特判掉越界情況也可以,但是比較麻煩)
至于為什么要更新到n+1列,是因為你更新到第i列的時候,可完全確定的是第i-1列的值,所以要完全確定第n列的值,需要第n+1列的狀態,只不過取? 讓第n+1列放置地雷個數為0? 的狀態就好了。
其實還有更簡單的方法,因為第一列的值定下來,通過s[1],第二列地雷肯定也是定的,而通過s[2]又可以確定s[3],以此類推,所以只要第一列的值確定了,后面的值都確定了,所以也可以直接遞推過去。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<stack> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define FF first #define SS second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 20000 + 5; const ll mod = 100000007; char s[MAX]; ll dp[MAX][10][10]; int main() {int T;cin>>T;while(T--) {scanf("%s",s+1);int n = strlen(s+1);s[n+1]=s[n]+9;for(int i = 1; i<=n+1; i++) {for(int j = 0; j<3; j++) {for(int k = 0; k<3; k++) dp[i][j][k]=0;}}for(int j = 0; j<3; j++) {if(j > s[1]-'0') continue;if(j == 1) dp[1][j][0]=2;else dp[1][j][0]=1;}for(int i = 2; i<=n+1; i++) {for(int j = 0; j<3; j++) { // if(i == n+1 && j>0) continue;for(int k = 0; k<3; k++) {if(s[i]-'0' < j+k) continue;if(s[i-1]-'0' < j+k) continue;//這句去掉其實也能過,但是有RE風險dp[i][j][k] += dp[i-1][k][s[i-1]-'0'-j-k];if(j == 1) dp[i][j][k] += dp[i-1][k][s[i-1]-'0'-j-k];dp[i][j][k] %= mod;}}}ll ans = 0;for(int k = 0; k<3; k++) ans = (ans+dp[n+1][0][k])%mod;printf("%lld\n",ans);}return 0 ; }?
總結
以上是生活随笔為你收集整理的【HDU - 5965】扫雷(dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【CodeForces - 618A】S
- 下一篇: 【CodeForces - 1152C