【日常刷題】[SCOI2005]掃雷(多維動態規劃)

[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皆可取,故可以得到:f[i][0][0][0]=f[i1][1][0][0]+f[i1][0][0][0](a[i]=0)f[i][0][0][0]=f[i-1][1][0][0]+f[i-1][0][0][0](a[i]=0)
我們同樣可以根據這個思路得到另外幾個轉移方程:
f[i][1][0][0]=f[i1][0][1][0]+f[i1][1][1][0](a[i]=1)f[i][1][0][0]=f[i-1][0][1][0]+f[i-1][1][1][0](a[i]=1)
f[i][0][1][0]=f[i1][1][0][1]+f[i1][0][0][1](a[i]=1)f[i][0][1][0]=f[i-1][1][0][1]+f[i-1][0][0][1](a[i]=1)
f[i][0][0][1]=f[i1][1][0][0]+f[i1][0][0][0](a[i]=1)f[i][0][0][1]=f[i-1][1][0][0]+f[i-1][0][0][0](a[i]=1)
f[i][1][1][0]=f[i1][0][1][1]+f[i1][1][1][1](a[i]=2)f[i][1][1][0]=f[i-1][0][1][1]+f[i-1][1][1][1](a[i]=2)
f[i][1][0][1]=f[i1][0][1][0]+f[i1][1][1][0](a[i]=2)f[i][1][0][1]=f[i-1][0][1][0]+f[i-1][1][1][0](a[i]=2)
f[i][0][1][1]=f[i1][0][0][1]+f[i1][1][0][1](a[i]=2)f[i][0][1][1]=f[i-1][0][0][1]+f[i-1][1][0][1](a[i]=2)
f[i][1][1][1]=f[i1][0][1][1]+f[i1][1][1][1](a[i]=3)f[i][1][1][1]=f[i-1][0][1][1]+f[i-1][1][1][1](a[i]=3)
狀態轉移完畢,我們需要考慮去輸出這個結果。顯然第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]);
    if (a[N]==2) printf("%d",f[N][1][1][0]);
    if (a[N]>=3) printf("0");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章