算法学社
記錄難忘的征途
posts - 141,comments - 220,trackbacks - 0

题目描述:

   1...n的排列 p1 ... pn ,位置 i 是good,当且仅当 abs(pi - i) = 1。 问大小为N ,恰好有K个位置是good的排列是多少?

算法分析:

   非常好的一道题,O(n^2) DP搞之。
   
   dp[n][k][p][q] 代表 大小为n,有k个good位置,p = 1代表 倒数第二个位置是n - 1 ,p = 2代表倒数第二个位置是 n, p = 0代表其他,q代表最后一个位置。

    然后转移不难想。。。。

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 #define re(i,n) for(int i = 0; i < n; i++)
 5 typedef long long ll;
 6 const int N = 1005;
 7 const int mod = (int)1e9+7;
 8 ll dp[N][N][3][3];
 9 int main(){
10     int n,k;
11     cin >> n >> k;
12     dp[1][0][0][1] = 1;
13     dp[2][0][1][2] = 1;
14     dp[2][2][2][1] = 1;
15     for(int i = 3; i <= n; i++){
16         for(int k = 0; k <= i; k++) {
17             //  * 2
18             re(p,2) re(q,3) dp[i][k][p][2] += dp[i-1][k][q][p+1];
19             re(q,3) dp[i][k][0][2] += dp[i-1][k][q][0];
20             // 2 1
21             if(k >= 2) re(q,2) dp[i][k][2][1] += dp[i-1][k-2][q][2];
22             // 2 0
23             re(q,3) dp[i][k][2][0] += dp[i-1][k][q][1];
24             if(k >= 1) re(q,3) dp[i][k][2][0] += dp[i-1][k-1][q][0];
25             // 0 1
26             dp[i][k][0][1]  += dp[i-1][k][2][1] + dp[i-1][k][2][0];
27             if(k >= 1) dp[i][k][0][1] += dp[i-1][k-1][0][0] + dp[i-1][k-1][0][1] + dp[i-1][k-1][1][0];
28             // 1 0
29             re(q,2) dp[i][k][1][0] += dp[i-1][k+1][q][2] * (k + 1);
30             if(i - 2 - k >= 0) re(q,2) dp[i][k][1][0] += dp[i-1][k][q][2] * (i - 2 - k);
31             // 0 0 vs 2 1
32             ll &ans = dp[i][k][0][0];
33             if(k - 1 >= 0) ans += dp[i-1][k+1][2][1] * (k - 1) ;
34                if(i - 1 - k >= 0) ans += dp[i-1][k][2][1] * (i - 1 - k);
35 //            cout<<"vs 2 1: "<<i<<" "<<k<<" "<<ans<<endl;
36             // 0 0 vs 2 0
37             ans += dp[i-1][k + 1][2][0] * k;
38             if( i - 2 - k >= 0) ans += dp[i-1][k][2][0] * (i - 2 - k);
39 //            cout<<"vs 2 0: "<<i<<" "<<k<<" "<<ans<<endl;
40             // 0 0 vs * 2
41 //            re(q,2) ans += dp[i-1][k+1][q][2] * (k + 1);
42 //            re(q,2) if(i - 2 - k >= 0)ans += dp[i-1][k][q][2] * (i - 2 - k);
43             // 0 0 vs * 0
44             re(q,2) ans += dp[i-1][k+1][q][0] * (k + 1);
45             if(i - 3 - k >= 0) re(q,2) ans += dp[i-1][k][q][0] * (i - 3 - k);
46 //            cout<<"vs * 0: "<<i<<" "<<k<<" "<<ans<<endl;
47             // 0 0 vs 0 1
48             ans += dp[i-1][k+1][0][1] * k;
49             if(i - 2- k >= 0) ans += dp[i-1][k][0][1] * (i - 2 - k);
50 //            cout<<"vs 0 1: "<<i<<" "<<k<<" "<<ans<<endl;
51             re(p,3) re(q,3) dp[i][k][p][q] %= mod;
52         }
53     }
54     ll ans = 0;
55     re(q,3) re(p,3){
56         ans += dp[n][k][p][q];
57 //        cout<<p<<" "<<q<<" "<<dp[n][k][p][q]<<endl;
58     }
59 //    int a,b,c,d; while(cin >> a >> b >> c >> d) cout<<dp[a][b][c][d]<<endl;
60     cout << ans % mod << endl;
61 }
62 
posted on 2013-03-22 16:11 西月弦 阅读(314) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理