P4622 [COCI2012-2013#6] JEDAN
阿新 • • 發佈:2018-09-05
pic 序列 eset src [1] bits bsp 一段 說明
題目背景
COCI
題目描述
有N個數排成一行(數值代表高度),最初所有的數都為零,你可以選擇連續的一段等高的數,將它們都增加1(除了開頭和結尾那個數)如下圖表示了兩次操作:
現在有一些數字看不清了,我們用-1表示,請你根據留下的數字,推出有多少 種可能的方案。使得留下的數字正好滿足上面的操作方法。
輸入輸出格式
輸入格式:第一行一個正整數N表示數的個數。 接下來一行N個數,依次表示每一個數的大小,-1表示看不清楚,你可以用任 意滿足條件的數代替。第i個數用hi?表示
輸出格式:一個數,表示所有可能的方案對1000000007求余的值。
輸入輸出樣例
輸入樣例#1:3
-1 2 -1
輸出樣例#1:
0
輸入樣例#2:
3
-1 -1 -1
輸出樣例#2:
2
輸入樣例#3:
6
-1 -1 -1 2 -1 -1
輸出樣例#3:
3
說明
- (1≤N≤10000)
- (−1≤hi≤10000)
Solution:
本題DP(為啥本題是黑題?也許評黑題考得是思維吧~!)。
首先由題意不難確定一些性質:
1、合法情況首尾一定為0
2、最高高度小於$n/2$
3、由2可以確定的是第$i$位高度:當$i\leq n/2$,$h_i$最高為$i-1$; 當$i>n/2$,$h_i$最高為$n-i$
4、由於每次選擇的是一段長度大於2的相等且連續的序列,而操作使$(l,r)+1$,所以相鄰兩位之差$\in[-1,1]$
然後就好做了。
考慮普通dp,定義狀態$f[i][j]$表示第$i$位高度為$j$的方案數,那麽初狀態$f[1][0]=1$,目標狀態$f[n][0]$。
由性質4的鄰位高度差絕對值$\leq 1$,不難得到狀態轉移方程:$f[i][j]=f[i-1][j-1]+f[i-1][j]+f[i-1][j+1]$
轉移時對於高度確定的就單次轉移,否則就枚舉可行高度並轉移。
這樣定義狀態會炸空間,但是每次轉移只與前一個數的狀態有關,所以直接滾掉就好了。
代碼:
/*Code by 520 -- 9.4*/ #include<bits/stdc++.h> #define il inline #define ll long long #define RE register #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--) using namespace std; const int mod=1e9+7; int n,a[10005],f[2][10005],cnt,siz; int main(){ scanf("%d",&n); For(i,1,n) scanf("%d",&a[i]); if(a[1]>0||a[n]>0) cout<<0,exit(0); a[1]=a[n]=0,f[1][0]=1,siz=2; while(siz<=n){ int up=siz; if(siz>n/2) up=n-siz+1; For(i,0,up-1) if(a[siz]==-1||i==a[siz]) f[cnt][i]=((ll)(i?f[!cnt][i-1]:0)+f[!cnt][i]+f[!cnt][i+1])%mod; cnt^=1,++siz; memset(f[cnt],0,sizeof(f[cnt])); } cout<<f[!cnt][0]; return 0; }
P4622 [COCI2012-2013#6] JEDAN