bzoj2817 [ZJOI2012]波浪

Description

 http://www.lydsy.com/JudgeOnline/upload/zjoi2012.pdf

正解:$dp$。

这道题好难啊。。

首先这道题里面有一个绝对值,这个很不好搞,我们考虑如何去掉。

我们只要按照从小到大的顺序插入所有数就行了。

那么插入一个数有很多种情况。

1.插入以后它两边都没有数。

2.插入以后它两边都有数。

3.插入以后它的一边有数。

4.插入在边界上,且它旁边没有数。

5.插入在边界上,且它旁边有数。

这$5$种情况对应$5$个不同的转移,于是我们可以设一个状态来表示这些转移。

设$f[i][j][k][l]$表示插入$i$个数,当前序列波动值为$j$,序列现在被分为$k$个连续的段,序列边界的状态为$l$,$l$为$0$表示边界没有数,为$1$表示边界有一个数,为$2$表示边界有两个数。

那么我们可以分几种情况转移,对应转移直接在代码里上注释吧,注意当$l$不同的时候转移系数也不同。

 1 #include <bits/stdc++.h>
 2 #define RG register
 3 #define ll long long
 4 #define M (4500)
 5 
 6 using namespace std;
 7 
 8 int n,m,k;
 9 
10 namespace db{ double f[2][9001][101][3]; }
11 namespace f128{ __float128 f[2][9001][101][3]; }
12 
13 template<class T>
14 
15 inline void pi(T ans,RG int k){
16   printf("%d.",(int)ans);
17   while (k--){
18     ans=(ans-(int)ans)*10;
19     if (!k) ans+=0.5;
20     printf("%d",(int)ans);
21   }
22   return;
23 }
24 
25 template<class T>
26 
27 inline void solve(T f[][9001][101][3]){
28   f[1][M-2][1][0]=1,f[1][M-1][1][1]=2,f[0][M][1][2]=1;
29   for (RG int i=2,cur=0,pre=1;i<=n;++i,pre=cur,cur^=1){
30     memset(f[cur],0,sizeof(f[cur]));
31     for (RG int j=0;j<=2*M;++j)
32       for (RG int k=1;k<=n-1;++k)
33     for (RG int l=0;l<=2;++l){
34       if (!f[pre][j][k][l]) continue;
35       if (j+2*i<=2*M) f[cur][j+2*i][k-1][l]+=f[pre][j][k][l]*(k-1); //插入以后两边都有数
36       if (j>=2*i) f[cur][j-2*i][k+1][l]+=f[pre][j][k][l]*(k+1-l); //插入以后两边都没有数
37       f[cur][j][k][l]+=f[pre][j][k][l]*(k*2-l); //插入以后一边有数
38       if (l<2){
39         if (j+i<=2*M) f[cur][j+i][k][l+1]+=f[pre][j][k][l]*(2-l); //插入在边界上,且旁边有数
40         if (j>=i) f[cur][j-i][k+1][l+1]+=f[pre][j][k][l]*(2-l); //插入在边界上,且旁边没有数
41       }
42     }
43   }
44   T ans=0; for (RG int i=M+m;i<=2*M;++i) ans+=f[n&1][i][1][2];
45   for (RG int i=2;i<=n;++i) ans/=i; pi(ans,k); return;
46 }
47 
48 int main(){
49 #ifndef ONLINE_JUDGE
50   freopen("wave.in","r",stdin);
51   freopen("wave.out","w",stdout);
52 #endif
53   cin>>n>>m>>k;
54   if (k<=8) solve(db::f);
55   else solve(f128::f);
56   return 0;
57 }
原文地址:https://www.cnblogs.com/wfj2048/p/7605464.html