BZOJ1996: [Hnoi2010]chorus 合唱队
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1996
题解:原来居然不会做!现在看着好水。。。
我们用f[i][j]表示排好i-j有多少种方案,然后发现好像不能转移。
因为i是放在队伍的左边还是右边只与i-1的身高有关。所以我们把状态加一维
f[i][j][0/1]表示把i-j排好并且最后一个插入的是 i 或 j,然后就可以转移了。
代码:
1 #include<cstdio> 2 3 #include<cstdlib> 4 5 #include<cmath> 6 7 #include<cstring> 8 9 #include<algorithm> 10 11 #include<iostream> 12 13 #include<vector> 14 15 #include<map> 16 17 #include<set> 18 19 #include<queue> 20 21 #include<string> 22 23 #define inf 1000000000 24 25 #define maxn 1500 26 27 #define maxm 500+100 28 29 #define eps 1e-10 30 31 #define ll long long 32 33 #define pa pair<int,int> 34 35 #define for0(i,n) for(int i=0;i<=(n);i++) 36 37 #define for1(i,n) for(int i=1;i<=(n);i++) 38 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 40 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 42 43 #define mod 19650827 44 45 using namespace std; 46 47 inline int read() 48 49 { 50 51 int x=0,f=1;char ch=getchar(); 52 53 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 54 55 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 56 57 return x*f; 58 59 } 60 int n,a[maxn],f[maxn][maxn][2]; 61 62 int main() 63 64 { 65 66 freopen("input.txt","r",stdin); 67 68 freopen("output.txt","w",stdout); 69 70 n=read(); 71 for1(i,n)a[i]=read(),f[i][i][0]=f[i][i][1]=1; 72 for1(i,n-1) 73 if(a[i]<a[i+1])f[i][i+1][0]=f[i][i+1][1]=1; 74 for2(l,2,n-1) 75 for1(i,n-l) 76 { 77 int j=i+l,tmp=0; 78 if(a[i]<a[j])tmp+=f[i+1][j][1]; 79 if(a[i]<a[i+1])tmp+=f[i+1][j][0]; 80 f[i][j][0]=tmp%mod; 81 tmp=0; 82 if(a[j]>a[i])tmp+=f[i][j-1][0]; 83 if(a[j]>a[j-1])tmp+=f[i][j-1][1]; 84 f[i][j][1]=tmp%mod; 85 //cout<<i<<' '<<j<<' '<<f[i][j][0]<<' '<<f[i][j][1]<<endl; 86 } 87 printf("%d\n",(f[1][n][0]+f[1][n][1])%mod); 88 89 return 0; 90 91 }