码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #384 (Div. 2) E. Vladik and cards 状压dp

时间:2017-10-09 22:30:23      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:表示   lan   mes   选择   splay   处理   强制   状压   数组   

Codeforces Round #384 (Div. 2) E. Vladik and cards 状压dp

大致题意:

给定一个序列an,序列中只有1~8的8个整数,让你选出一个子序列,子序列应该满足下列两个要求

1.子序列中不同整数出现的次数极差小于或等于1

2.子序列中整数分布是连续的,即子序列的相同整数必须分布在一起, 如  2 2 2 2 1 1 1 1 3 3 3 等.

求出符合要求的子序列的最大长度.

题解:

嗯,对于第一个条件,可以知道的是对于每个符合条件的子序列而言,其中的每个整数的出现的次数最多会有2个不同的值,

比如说1出现了 num 次,那么2只可能出现 num 次或者出现 num+1 次.

    对于第二个条件,可以强制使得数字 i 全部出现在一起, 那么我们有必要先预处理出这样一个数组next[i][j][k] 来完成这个过程, next[i][j][k] 表示 从原数组的第i 个位置开始, 大小为j 的数出现次数为k的那个位置.

    好了, 当我们知道了num 的值后,我们对于每个数1~8 只要枚举他们长度为 0 (不选), num , num+ 1 这 3 种情况就可以了, 于是我们设DP[i][j] 表示 8个数的选择情况为i,长度为num+1的数字个数为j时可以达到的最远的位置,

那么当我们DP完了以后,只要枚举DP[255][j] (j = 1 .. 8) , 如果 DP[255][j] <= n + 1(结束位置在原数组内部) ,就更新答案......

  

技术分享
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1050;
 4 int a[maxn],dp[maxn][9],next[maxn][9][maxn],n,cnt[maxn],ans = 0;
 5 inline int ask(int k){return (1 << (k - 1));}
 6 int main(){
 7     scanf("%d",&n);
 8     for (int i = 1 ; i <= n ; ++i) scanf("%d",&a[i]);
 9     for (int i = 1 ; i <= n ; ++i){
10         for (int j = 1 ; j <= 8 ; ++j) cnt[j] = 0;
11         for (int j = 1 ; j <= 8 ; ++j) for (int k = 1 ; k <= n ; ++k) next[i][j][k] = 1e9;
12         for (int j = i ; j <= n ; ++j) next[i][a[j]][++cnt[a[j]]] = j;
13     }
14     for (int num = 0 ; num * 8 <= n ; ++num){
15         for (int i = 0 ; i < 256 ; ++i) for (int j = 0 ; j <= 8 ; ++j) dp[i][j] = 1e9;
16         dp[0][0] = 1;
17         for (int i = 0 ; i < 256 ; ++ i) for (int j = 0 ; j <= 8 ; ++j) for (int k = 1 ; k <= 8 ; ++k){
18             if ((ask(k) & i) || dp[i][j] > n) continue;
19             dp[i ^ ask(k)][j] = min(dp[i ^ ask(k)][j],next[dp[i][j]][k][num] + 1);
20             dp[i ^ ask(k)][j + 1] = min(dp[i ^ ask(k)][j + 1],next[dp[i][j]][k][num + 1] + 1);
21         }
22         for (int j = 0 ; j <= 8 ; ++j) if (dp[255][j] <= n + 1) ans = max(ans,8 * num + j);
23     }
24     cout<<ans<<endl;
25     return 0;
26 }
Codeforces Round #384 (Div. 2)E

 

Codeforces Round #384 (Div. 2) E. Vladik and cards 状压dp

标签:表示   lan   mes   选择   splay   处理   强制   状压   数组   

原文地址:http://www.cnblogs.com/juruohx/p/7642872.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!