bzoj1088: [SCOI2005]掃雷Mine 題解

1088: [SCOI2005]掃雷Mine
Description

  相信大家都玩過掃雷的遊戲。那是在一個n*m的矩陣裏面有一些雷,要你根據一些信息找出雷來。萬聖節到了
,“餘”人國流行起了一種簡單的掃雷遊戲,這個遊戲規則和掃雷一樣,如果某個格子沒有雷,那麼它裏面的數字
表示和它8連通的格子裏面雷的數目。現在棋盤是n×2的,第一列裏面某些格子是雷,而第二列沒有雷,如下圖:
由於第一列的雷可能有多種方案滿足第二列的數的限制,你的任務即根據第二列的信息確定第一列雷有多少種擺放
方案。

Input

  第一行爲N,第二行有N個數,依次爲第二列的格子中的數。(1<= N <= 10000)

Output

  一個數,即第一列中雷的擺放方案數。

Sample Input

2
1 1

Sample Output

2

題解:
因爲只有一行,我們可以靠分析來求出答案。
答案只有0,1,2這三種,因爲第二行顯示的雷數是固定的,第一行除了一,二兩個格子也隨之固定。
第一行第一,二兩個格子只跟第二行的第一個格子有關(在我們的設想下),那麼我們假設第一,二格有無雷,然後check一趟就好了。

現在考慮check的寫法,設Fi 爲第i個格子有無雷,Ai 爲第二行顯示的雷輸。
顯然Fi+1=AiFiFi1
爲什麼呢?因爲(2,i) 上顯示的雷數是(1,i1)(1,i)(1,i+1) 是否有雷的和,也就是Ai=Fi1+Fi+Fi+1 ,所以Fi+1=AiFiFi1
注意,如果AiFiFi1<0 或者ANFN1FN0 那麼check就失敗了。

最後附上代碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N,Ans,A[10005],F[10005];
bool check(){
    for (int i=2;i<=N;i++){
        if (A[i]-F[i]-F[i-1]<0) return 0;
        F[i+1]=A[i]-F[i]-F[i-1];
    }
    if (A[N]-F[N-1]-F[N]^0) return 0;
    return 1;
}
int main()
{
    scanf("%d",&N);
    for (int i=1;i<=N;i++) scanf("%d",&A[i]);
    if (A[1]==0) Ans+=check();
    else if (A[1]==1){
        F[1]=1;Ans+=check();
        memset(F,0,sizeof F);
        F[2]=1;Ans+=check();
    }
    else F[1]=F[2]=1,Ans+=check();
    printf("%d\n",Ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章