codeforces 814E An unavoidable detour for home

题目链接

 

正解:$dp$。

感觉这道题就是中国象棋的加强版。。我们要发现一些性质。

首先就是这个图肯定是一个按照$bfs$序分层的图,且每个点只往自己上面那一层连了一条边,每个点不可能向自己的上面超过两层的点连边。

又因为$l_{i}\leq l_{i+1}$,所以实际上$bfs$序相同的点是连续的。

然后我们就可以$dp$了,设$f[i][a][b][c][d]$表示处理了前i个点,上一层还有a个点度数为1,b个点度数为2,这一层还有c个点度数为1,d个点度数为2。

然后我们直接转移就行了,转移就是对于当前点,枚举它的连边情况,它肯定会往上一层连一条边,同时也可能往自己这一层连边,剩下的边就留给下一层就行了。

最终答案就是$f[n][0][0][0][0]$。

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define rhl (1000000007)
 6 
 7 using namespace std;
 8 
 9 int f[2][51][51][51][51],du[51],n;
10 //f[i][a][b][c][d]表示处理了前i个点,上一层还有a个点度数为1,b个点度数为2,这一层还有c个点度数为1,d个点度数为2
11 
12 il int gi(){
13   RG int x=0,q=1; RG char ch=getchar();
14   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
15   if (ch=='-') q=-1,ch=getchar();
16   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
17   return q*x;
18 }
19 
20 il void add(RG int &x,RG int v){
21   x+=v; if (x>=rhl) x-=rhl; return;
22 }
23 
24 int main(){
25 #ifndef ONLINE_JUDGE
26   freopen("home.in","r",stdin);
27   freopen("home.out","w",stdout);
28 #endif
29   n=gi();
30   for (RG int i=1;i<=n;++i) du[i]=gi();
31   f[0][du[1]==2][du[1]==3][du[2]==2][du[2]==3]=1;
32   for (RG int i=2,pre=1,cur=0;i<n;++i,pre=cur,cur^=1){
33     memset(f[pre],0,sizeof(f[pre]));
34     for (RG int a=0;a<=i;++a)
35       for (RG int b=0;a+b<=i;++b)
36     for (RG int c=0;a+b+c<=i;++c)
37       for (RG int d=0,res;a+b+c+d<=i;++d){
38         res=f[cur][a][b][c][d]; if (!res) continue;
39         if (!a && !b){
40           if (c || d) add(f[cur][c][d][0][0],res); continue;
41         }
42         if (du[i+1]==2){
43           if (a){
44         add(f[pre][a-1][b][c+1][d],1LL*res*a%rhl);
45         if (c) add(f[pre][a-1][b][c-1][d],1LL*res*a*c%rhl);
46         if (d) add(f[pre][a-1][b][c+1][d-1],1LL*res*a*d%rhl);
47           }
48           if (b){
49         add(f[pre][a+1][b-1][c+1][d],1LL*res*b%rhl);
50         if (c) add(f[pre][a+1][b-1][c-1][d],1LL*res*b*c%rhl);
51         if (d) add(f[pre][a+1][b-1][c+1][d-1],1LL*res*b*d%rhl);
52           }
53         } else{
54           if (a){
55         add(f[pre][a-1][b][c][d+1],1LL*res*a%rhl);
56         if (c) add(f[pre][a-1][b][c][d],1LL*res*a*c%rhl);
57         if (d) add(f[pre][a-1][b][c+2][d-1],1LL*res*a*d%rhl);
58         if (c && d) add(f[pre][a-1][b][c][d-1],1LL*res*a*c*d%rhl);
59         if (c>=2) add(f[pre][a-1][b][c-2][d],1LL*res*(a*c*(c-1)>>1)%rhl);
60         if (d>=2) add(f[pre][a-1][b][c+2][d-2],1LL*res*(a*d*(d-1)>>1)%rhl);
61           }
62           if (b){
63         add(f[pre][a+1][b-1][c][d+1],1LL*res*b%rhl);
64         if (c) add(f[pre][a+1][b-1][c][d],1LL*res*b*c%rhl);
65         if (d) add(f[pre][a+1][b-1][c+2][d-1],1LL*res*b*d%rhl);
66         if (c && d) add(f[pre][a+1][b-1][c][d-1],1LL*res*b*c*d%rhl);
67         if (c>=2) add(f[pre][a+1][b-1][c-2][d],1LL*res*(b*c*(c-1)>>1)%rhl);
68         if (d>=2) add(f[pre][a+1][b-1][c+2][d-2],1LL*res*(b*d*(d-1)>>1)%rhl);
69           }
70         }
71       }
72   }
73   cout<<f[n&1][0][0][0][0]; return 0;
74 }

 

posted @ 2017-11-09 15:33  wfj_2048  阅读(345)  评论(0编辑  收藏  举报