1. 程式人生 > >【日常刷題】[SCOI2005]掃雷(多維動態規劃)

【日常刷題】[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 [ i 1 ] [ 1 ]
[ 0 ] [ 0 ] + f [ i 1 ] [ 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 [ i 1 ] [ 0 ] [ 1 ] [ 0 ] + f [ i 1 ] [ 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 [ i 1 ] [ 1 ] [ 0 ] [ 1 ] + f [ i 1 ] [ 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 [ i 1 ] [ 1 ] [ 0 ] [ 0 ] + f [ i 1 ] [ 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 [ i 1 ] [ 0 ] [ 1 ] [ 1 ] + f [ i 1 ] [ 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 [ i 1 ] [ 0 ] [ 1 ] [ 0 ] + f [ i 1 ] [ 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 [ i 1 ] [ 0 ] [ 0 ] [ 1 ] + f [ i 1 ] [ 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 [ i 1 ] [ 0 ] [ 1 ] [ 1 ] + f [ i 1 ] [ 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]