HDU 5965 扫雷 By Assassin

来源:互联网 发布:杭州淘宝小镇 编辑:程序博客网 时间:2024/06/06 01:43

扫雷

Problem Description
扫雷游戏是晨晨和小璐特别喜欢的智力游戏,她俩最近沉迷其中无法自拔。
该游戏的界面是一个矩阵,矩阵中有些格子中有一个地雷,其余格子中没有地雷。 游戏中,格子可能处于己知和未知的状态。如果一个己知的格子中没有地雷,那么该 格子上会写有一个一位数,表示与这个格子八连通相邻的格子中地雷总的数量。
现在,晨晨和小璐在一个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
000

Sample Output
6
1

讲真没想到我这么水。。。这个铁牌题目都坑死在了这里。。。而且我xjbg出了一种麻烦的方法。。。

方法一:
思路:我们其实可以发现,只要确定了第一列的状态,就可以确定所有后面的状态了。。。那么这个怎么做,首先是枚举初始状态,也就3种情况,但是也可能和第一个数有关。之后枚举,每次求出正常的状态,用dp[i]记录i位置列应该有几个。那么每次我们计算一下,碰到1就×2取膜就好。,注意1位的时候特判一下。还有一个别用string。。。用char。。。

代码

#include<bits/stdc++.h>#define input freopen("input.txt","r",stdin)using namespace std; long long a[10005],dp[10005];char s[10005];int main(){    input;    int t,n,len,i,j,k;    long long ans;    while(scanf("%d",&t)!=EOF){        while(t--){            scanf("%s",s);            len=strlen(s);            for(i=0;i<len;i++){                a[i+1]=s[i]-'0';            }            if(len==1){                if(s[0]=='0'||s[0]=='2')  cout<<1<<endl;                else if(s[0]=='1')        cout<<2<<endl;                 else                      cout<<0<<endl;                continue;            }            dp[0]=0;            ans=0;            for(k=0;k<=a[1];k++){                if(k>2)  break;                memset(dp,0,sizeof(dp));                dp[1]=k;                int flag=1;                for(i=2;i<=len;i++){                    dp[i]=a[i-1]-dp[i-1]-dp[i-2];                    if(dp[i]<0||dp[i]>2) {                        flag=0;                        break;                    }                }                if(flag==1){                    for(i=1;i<=len;i++){                        if(a[i]!=dp[i-1]+dp[i]+dp[i+1]){                            flag=0;                            break;                        }                    }                }                if(!flag) continue;                long long key=1;                for(i=1;i<=len;i++){                    if(dp[i]==1){                        key=(key*2)%100000007;                    }                }                ans+=key;            }            cout<<ans%100000007<<endl;        }    }    return 0; }

方法二:
思路:就简直不是方法,麻烦版本的dp,你敢想我用了三维!大概的转移状态dp[i][j][k]代表第i个位置,当前准备使用j个,这个需要遍历,在后面必须用k个。注意这不算是严格的动规,因为第三维其实只是相当于一个调用的接口,指后一个如果用k个,向前找必须对应后面必须是可的位置。
所以这个需要遍j和k,每次首先判断这样的求
的下一个值是否合法(只能是0-2)然后转移,[[

代表第0个位置,选择0个下一个接0-2都可以。

#include <bits/stdc++.h>using namespace std;int a[10005];long long dp[10005][3][3];char s[10005];int main(){    //freopen("input.txt","r",stdin);    int t,i,j,k,len;    scanf("%d",&t);    while(t--){        scanf("%s",s);        len=strlen(s);        for(i=0;i<len;i++){            a[i+1]=s[i]-'0';        }        memset(dp,0,sizeof(dp));         dp[0][0][0]=1;        dp[0][0][1]=1;        dp[0][0][2]=1;        for(i=1;i<=len;i++){            for(j=0;j<=2;j++){                if(a[i]-j>=0&&a[i]-j<=2){                    dp[i][j][a[i]-j]=dp[i-1][0][j];                    if(j==1) {                        dp[i][j][a[i]-j]*=2;                        if(dp[i][j][a[i]-j]>=100000007)                            dp[i][j][a[i]-j]-=100000007;                    }                }                if(a[i]-j-1>=0&&a[i]-j-1<=2){                    dp[i][j][a[i]-j-1]=(dp[i-1][1][j]);                    if(j==1){                        dp[i][j][a[i]-j-1]*=2;                        if(dp[i][j][a[i]-j-1]>=100000007)                            dp[i][j][a[i]-j-1]-=100000007;                        }                 }                if(a[i]-j-2>=0&&a[i]-j-2<=2){                    dp[i][j][a[i]-j-2]=dp[i-1][2][j];                    if(j==1){                        dp[i][j][a[i]-j-2]*=2;                        if(dp[i][j][a[i]-j-2]>=100000007)                        dp[i][j][a[i]-j-2]-=100000007;                        }                 }            }        }        long long ans=0;        for(j=0;j<=2;j++){            ans+=dp[len][j][0];        }        cout<<ans%100000007<<endl;    }    return 0;}
0 0
原创粉丝点击