【每日一题】扫雷
[SCOI2005]扫雷MINE
https://ac.nowcoder.com/acm/problem/20241
题目描述
相信大家都玩过扫雷的游戏。那是在一个n*m的矩阵里面有一些雷,要你根据一些信息找出雷来。
万圣节到了 ,“余”人国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字 表示和它8连通的格子里面雷的数目。
现在棋盘是n×2的,第一列里面某些格子是雷,而第二列没有雷,如下图: 由于第一列的雷可能有多种方案满足第二列的数的限制,你的任务即根据第二列的信息确定第一列雷有多少种摆放方案。
输入描述:
第一行为N,第二行有N个数,依次为第二列的格子中的数。(1 ≤ N ≤ 10000)
输出描述:
一个数,即第一列中雷的摆放方案数。
题解
设四维数组f[N][2][2][2],一维第二列位置,二维三维四维存i-1,i,i+1是否有雷
方程:
1.a[i]为0
2.a[i]为1
3.a[i]为2
4.a[i]为3
最后
如果a[n]=0,ans=f[n][0][0][0]
如果a[n]=1,ans=f[n][1][0][0]+f[n][0][1][0];
如果a[n]=2,ans=f[n][1][1][0];
如果a[n]=3,无解
代码
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define lowbit(x) x&(-x) #define iter set<int>::iterator typedef long long ll; typedef pair<int,int> pii; typedef pair<ll, ll> pll; const int N = 1e5 + 5; const int mod = 1e4 + 7; const int INF = 0x3f3f3f3f; const int dir[4][2]={-1,0,1,0,0,-1,0,1}; ll qpow(ll x,ll y){ ll ans=1,t=x; while(y>0){ if(y&1)ans*=t,ans%=mod; t*=t,t%=mod; y>>=1; } return ans; } int a[10001]; int f[10001][2][2][2]; void solve(){ int n;cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; f[0][0][0][0]=f[0][0][0][1]=1; for(int i=1;i<=n;i++){ if(!a[i])f[i][0][0][0]=f[i-1][0][0][0]+f[i-1][1][0][0]; if(a[i]==1){ f[i][1][0][0]=f[i-1][0][1][0]+f[i-1][1][1][0]; f[i][0][1][0]=f[i-1][0][0][1]+f[i-1][1][0][1]; f[i][0][0][1]=f[i-1][0][0][0]+f[i-1][1][0][0]; } if(a[i]==2){ f[i][1][1][0]=f[i-1][0][1][1]+f[i-1][1][1][1]; f[i][1][0][1]=f[i-1][0][1][0]+f[i-1][1][1][0]; f[i][0][1][1]=f[i-1][0][0][1]+f[i-1][1][0][1]; } if(a[i]==3)f[i][1][1][1]=f[i-1][0][1][1]+f[i-1][1][1][1]; } int ans=0; if(!a[n])ans=f[n][0][0][0]; if(a[n]==1)ans=f[n][1][0][0]+f[n][0][1][0]; if(a[n]==2)ans=f[n][1][1][0]; cout<<ans; } int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); //int t;cin>>t; //while(t--)solve(),cout<<endl; solve(); return 0; }