输入输出格式
输入格式:
第一行为N,第二行有N个数,依次为第二列的格子中的数。(1<= N <= 10000)
输出格式:
一个数,即第一列中雷的摆放方案数。
输入输出样例
输入样例#1:
2 1 1
输出样例#1:2
题目大意 有两列 右边的列的数字表示这个格子的八个方向的雷的数量 求雷位置的方案数。
题解
递推
看错题了 写了个错的dfs水了10分...我还是放一下吧...
每个格子有两个状态 有雷和没有雷 然后当第一个格子放雷时,和不放雷时,进行判断一下
行不行 所以方案数只有0、1、2种,注意最后判断n+1个格子有没有雷
代码
10分错的dfs //
#include<iostream> #include<cstdio> using namespace std; int ans,n,minn=0x7ffff,cnt[10005]; bool ok(){ for(int i=1;i<=n;i++)if(cnt[i])return 0; return 1; } bool check(int k){ if((k==1||k==2)&&n>=3) if(cnt[1]&&cnt[2]&&cnt[3])return 1; else return 0; if((k==n||k==n-1)&&n>=3) if(cnt[n]&&cnt[n-1]&&cnt[n-2])return 1; else return 0; if(n<3)for(int i=1;i<=n;i++)if(!cnt[i])return 0; else return 1; for(int i=k;i<=k+2;i++)if(!cnt[i])return 0; for(int j=k;j>=k-2;j--)if(!cnt[j])return 0; return 1; } void put(int k){ if(n<=3)for(int i=1;i<=n;i++)cnt[i]--; else if(k<=2)cnt[1]--,cnt[2]--,cnt[3]--; else { for(int i=k;i<=k+2;i++)cnt[i]--; for(int i=k-1;i>=k-2;i--)cnt[i]--; } } void back(int k){ if(n<=3)for(int i=1;i<=n;i++)cnt[i]++; else if(k<=2)cnt[1]++,cnt[2]++,cnt[3]++; else { for(int i=k;i<=k+2;i++)cnt[i]++; for(int i=k-1;i>=k-2;i--)cnt[i]++; } } void dfs(int k){ if(k==n+1){ if(ok())ans++; return ; } if(check(k)){ put(k); dfs(k+1); back(k); } dfs(k+1); return; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&cnt[i]),minn=min(minn,cnt[i]); if(n<=3&&minn==0){ printf("0 "); return 0; } dfs(1); printf("%d ",ans); return 0; }
正解
#include<iostream> #include<cstdio> using namespace std; int n,ans,a[10005],b[10003]; bool ok(){ for(int i=2;i<=n;i++){ b[i]=a[i-1]-b[i-1]-b[i-2]; if(b[i]!=0&&b[i]!=1)return 0; if(i==n&&(a[n]-b[n]-b[n-1])!=0)return 0; } return 1; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); b[1]=1; if(ok())ans++; b[1]=0; if(ok())ans++; printf("%d",ans); return 0; }
今天下午晕呼呼的(~ o ~)~zZ 效率低真讨厌╭(╯^╰)╮