簡單的遊戲(10進位制輪廓線dp)
阿新 • • 發佈:2018-12-01
題目:
思路:考慮按順序進行填充,當前位置只受上一個影響和左邊的一個影響。
假設有5列,那麼每一列用一個數來填充,最大是99999,最小是00000.
由於m<=6,所以最大狀態是999999,可以直接從0開始列舉,到999999複雜度為1e6。
dp[sta][cur] 表示當狀態為sta時的方案數,由於當前狀態由前一個狀態轉移過來,所以cur只需要0或1就行。
思路和普通的二進位制表示的輪廓線dp類似。
程式碼:
#include <bits/stdc++.h> using namespace std; const int maxn=1e6+7; typedef long long ll; const int mod=1e9+7; ll dp[maxn][2]; char s[10][10]; int isp[21] = {0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0}; int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%s",s[i]); } int sta=1; for(int i=0;i<m;i++) sta*=10; dp[0][0]=1; int cur=0; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { cur^=1; for(int k=0;k<sta;k++) { dp[k][cur]=0; } for(int k=0;k<sta;k++) { int f=k/(sta/10); int last=k%10; if(dp[k][cur^1]==0) continue; for(int add=0;add<10;add++) { if((s[i][j]=='?'||(s[i][j]=='0'+add))&&(!i||(isp[f+add]))&&(!j||isp[last+add])) //需要記錄s[i][j]=='0'+add的原因是是因為要保留前一狀態,因為你會發現,這個狀態進行轉移以後,其實值是沒有變化的。 { int kk=k-f*(sta/10); kk=kk*10+add; dp[kk][cur]+=dp[k][cur^1]; } } } } } ll ans=0; for(int i=0;i<sta;i++) { ans+=dp[i][cur]; } printf("%lld\n",ans); return 0; }