题意:中文
思路:定义dp【i】为第i列埋的地雷数,num[i]为第i个格子上面标着的数字。所以有dp[i]=num[i-1]-dp[i-2]-dp[i-1](当有三个连续的列时) dp[i]=num[i-1]-dp[i-1],当此时为第一列。
定义好了以后,还有一个关键的地方在于:如果一列的地雷数为0或2,则这一列只有一种方法,如果有一个地雷则有两种放法。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int maxn=1e4+50;
const long long mod=1e8+7;
int T,dp[maxn],n;
long long ans;
char s[maxn];
void solve(){
memset(dp,0,sizeof(dp));
ans=0;
for(int i=0;i<=s[0]-'0';i++){
dp[0]=i;
if(dp[0]>2) break;
int j;
for(j=1;j<n;j++){
int k;
if(j==1)
k=s[j-1]-'0'-dp[j-1];
else k=s[j-1]-'0'-dp[j-1]-dp[j-2];
if(k>2||k<0) break;
dp[j]=k;
}
if(j<n) continue;
if(dp[n-1]+dp[n-2]!=s[n-1]-'0') continue;
long long res=1;
for(int j=0;j<n;j++){
if(dp[j]==0||dp[j]==2) res*=1;
else res*=2;
res%=mod;///每次需要取模
}
ans+=res;
ans%=mod;
}
}
int main(){
while(scanf("%d",&T)!=EOF){
for(int cas=1;cas<=T;cas++){
scanf("%s",s);
n=strlen(s);
solve();
printf("%lld\n",ans);
}
}
return 0;
}
刚开始做的时候没有注意到数据规模,用了回溯法来做,结果TLE。(用回溯法做的题目一般数据规模较小).
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int maxn=1e4+50;
int T,length,d[maxn],cnt,dirx[]={-1,1,0},diry[]={1,-1},tmp;
char s[maxn];
bool vis[3][maxn];
void dfs(int num,int cur2){///num为方格内的数字,cur2为列数
if(!num){
if(cur2+1==length){
cnt++;
cnt%=mod;
return;
}
int tot=0;
for(int i=0;i<2;i++)
for(int j=0;j<3;j++)
if(vis[1+diry[i]][cur2+1+dirx[j]]) tot++;
int temp=s[cur2+1]-'0';
if(temp-tot<0) return;
dfs(temp-tot,cur2+1);
}
else{
for(int i=0;i<2;i++)
for(int j=0;j<3;j++)
if(cur2+dirx[j]>=0&&cur2+dirx[j]<length&&!vis[1+diry[i]][cur2+dirx[j]]){
vis[1+diry[i]][cur2+dirx[j]]=true;
dfs(num-1,cur2);
vis[1+diry[i]][cur2+dirx[j]]=false;
}
}
}
int main(){
while(scanf("%d",&T)!=EOF){
for(int cas=1;cas<=T;cas++){
scanf("%s",s);
length=strlen(s);
cnt=0;
memset(vis,0,sizeof(vis));
dfs(s[0]-'0',0);
if(cnt>1) cnt>>=1;
printf("%lld\n",cnt);
}
}
return 0;
}