【日常刷題】[SCOI2005]掃雷(多維動態規劃)
阿新 • • 發佈:2018-11-06
[SCOI2005]掃雷
我們對於這道題,我們可以採用DP的方法來解決。
我們設f[i][0/1][0/1][0/1]表示滿足前i個條件限制,第i-1,i,i+1分別放(1)和不放(0)的方案數。
對於a[i](第二列的數字),我們採用分類討論的方法來進行狀態轉移。
當a[i]=0時,第i-1和i件物品都不取,因此轉移的第3維和第4維必須為0,但是第i-2件物品可以取也可不取,因此第二維01皆可取,故可以得到:
我們同樣可以根據這個思路得到另外幾個轉移方程:
狀態轉移完畢,我們需要考慮去輸出這個結果。顯然第4維為1的情況是不能輸出的,根據n的取值做具體的累加。至於具體的實現請看程式碼。
CODE
#include<bits/stdc++.h>
using namespace std;
#define MAXN 12000
int f[MAXN][2][2][2],a[MAXN];
inline void read(int &be_readNUM)
{
int s=0,w=1;char c=getchar();
while (c<'0' || c>'9') c=getchar();
while (c<='9' && c>='0') {s=s*10+c-'0'; c=getchar();}
be_readNUM=s*w;return;
}
int main()
{
int N;read(N);
for (int i=1;i<=N;++i) read(a[i]);
f[0][0][0][0]=f[0][0][0][1]=1;
for (int i=1;i<=N;++i)
{
if (a[i]==0) f[i][0][0][0]=f[i-1][1][0][0]+f[i-1][0][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][1][0][1]+f[i-1][0][0][1];
f[i][0][0][1]=f[i-1][1][0][0]+f[i-1][0][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];
}
if (a[N]==0) printf("%d",f[N][0][0][0]);
if (a[N]==1) printf("%d",f[N][0][1][0]+f[N][1][0][0]