【HYSBZ - 1088 】扫雷Mine (简单dp)
題干:
相信大家都玩過掃雷的游戲。那是在一個n*m的矩陣里面有一些雷,要你根據(jù)一些信息找出雷來。萬圣節(jié)到了
,“余”人國流行起了一種簡單的掃雷游戲,這個游戲規(guī)則和掃雷一樣,如果某個格子沒有雷,那么它里面的數(shù)字
表示和它8連通的格子里面雷的數(shù)目?,F(xiàn)在棋盤是n×2的,第一列里面某些格子是雷,而第二列沒有雷,如下圖:?
由于第一列的雷可能有多種方案滿足第二列的數(shù)的限制,你的任務即根據(jù)第二列的信息確定第一列雷有多少種擺放
方案。
Input
第一行為N,第二行有N個數(shù),依次為第二列的格子中的數(shù)。(1<= N <= 10000)
Output
一個數(shù),即第一列中雷的擺放方案數(shù)。
Sample Input
2 1 1
Sample Output
2
Hint
解題報告:
? ? 簡單但是十分不錯的dp題。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 10000 + 5; ll dp[MAX][2][2];//dp[i][j][k]截止第i行,這一行為j,上一行為k。 int a[MAX]; int main() {int n;cin>>n;for(int i = 1; i<=n; i++) scanf("%d",a+i); // if(a[1] != 0) {dp[1][1][0]=dp[1][1][1]=dp[1][0][0]=dp[1][0][1]=1; // } // dp[1][0][0] = dp[1][1][0]=1;//dp[][這行][上行] dp[i行][i行][i-1行]for(int i = 2; i<=n+1; i++) {if(a[i-1] == 1) {dp[i][1][0] += dp[i-1][0][0];dp[i][0][0] += dp[i-1][0][1];dp[i][0][1] += dp[i-1][1][0];//默認其余的為0.。 }if(a[i-1] == 0) {dp[i][0][0] += dp[i-1][0][0];}if(a[i-1] == 2) {dp[i][1][0] += dp[i-1][0][1];dp[i][1][1] += dp[i-1][1][0];dp[i][0][1] += dp[i-1][1][1];}if(a[i-1] == 3) {dp[i][1][1] += dp[i-1][1][1];}}ll ans = 0;ans = /*dp[n+1][1][0] + dp[n+1][1][1] +*/ dp[n+1][0][0] + dp[n+1][0][1];printf("%lld\n",ans);return 0 ;}總結:
注意合法狀態(tài)和不更新狀態(tài)的區(qū)別!!!有的是非法狀態(tài)(此題中就要是0而不是INF,因為表示的是方法數(shù)),有的是不更新狀態(tài)(此題中也是0,但是是無法到達狀態(tài),而不是非法狀態(tài)),也就是,都是0但是含義不同!!
之所以更新成1,也是因為方法數(shù)是1。(只選這一種方法,所以方法數(shù)是1啊)
其實這個代碼是不對的(雖然也AC了),初始化狀態(tài)的時候應該用下面那個注釋掉的,因為不然的話輸入1 1就會錯。,。。
注意不能輸出dp[n][][]的四個狀態(tài)的和!!!因為那樣就不一定滿足第n行的性質了!!!所以一定要讓狀態(tài)轉移結束以后再找結果!!不能直接輸出第n行的四個狀態(tài)的和。
附一種解法:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; ll n,x,y,c; const int MAX = 10000 + 5; ll dp[MAX][2][2];//dp[i][j][k]截止第i行,這一行為j,上一行為k。 int a[MAX]; int main() {int n;cin>>n;for(int i = 1; i<=n; i++) scanf("%d",a+i);dp[1][0][0] = dp[1][1][0]=1;//dp[][這行][上行] dp[i行][i行][i-1行]for(int i = 2; i<=n+1; i++)for(int las = 0 ; las <= 1 ; las++)for(int llas = 0; llas<=1; llas++)for(int now = 0; now<=1; now++)if(las+llas+now == a[i-1])dp[i][now][las] += dp[i-1][las][llas] ;ll ans = dp[n+1][0][0] + dp[n+1][0][1];printf("%lld\n",ans);return 0 ; }或者:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; ll n,x,y,c; const int MAX = 10000 + 5; ll dp[MAX][2][2];//dp[i][j][k]截止第i行,這一行為j,上一行為k。 int a[MAX]; int main() {int n;cin>>n;for(int i = 1; i<=n; i++) scanf("%d",a+i);dp[0][0][0] = dp[0][1][0]=1;//dp[][下一行][這一行行] dp[i行][i+1行][i行]for(int i = 1; i<=n; i++)for(int las = 0 ; las <= 1 ; las++)for(int llas = 0; llas<=1; llas++)for(int now = 0; now<=1; now++)if(las+llas+now == a[i])dp[i][now][las] += dp[i-1][las][llas] ;ll ans = dp[n][0][0] + dp[n][0][1];printf("%lld\n",ans);return 0 ; }?
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的【HYSBZ - 1088 】扫雷Mine (简单dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 光大信用卡额度怎么提升 要想快速提额看这
- 下一篇: 建行10万额度信用卡办理条件 并不是人人