Codeforces Round #384 (Div. 2)E.Vladik and cards【二分+状压dp】
来源:互联网 发布:log4j数据存进mongodb 编辑:程序博客网 时间:2024/05/01 23:50
Vladik was bored on his way home and decided to play the following game. He tookn cards and put them in a row in front of himself. Every card has a positive integer number not exceeding8 written on it. He decided to find the longest subsequence of cards which satisfies the following conditions:
- the number of occurrences of each number from 1 to8 in the subsequence doesn't differ by more then1 from the number of occurrences of any other number. Formally, if there areck cards with numberk on them in the subsequence, than for all pairs of integers the condition|ci - cj| ≤ 1 must hold.
- if there is at least one card with number x on it in the subsequence, then all cards with numberx in this subsequence must form a continuous segment in it (but not necessarily a continuous segment in the original sequence). For example, the subsequence[1, 1, 2, 2] satisfies this condition while the subsequence[1, 2, 2, 1] doesn't. Note that[1, 1, 2, 2] doesn't satisfy the first condition.
Please help Vladik to find the length of the longest subsequence that satisfies both conditions.
The first line contains single integer n (1 ≤ n ≤ 1000) — the number of cards in Vladik's sequence.
The second line contains the sequence of n positive integers not exceeding8 — the description of Vladik's sequence.
Print single integer — the length of the longest subsequence of Vladik's sequence that satisfies both conditions.
31 1 1
1
88 7 6 5 4 3 2 1
8
241 8 1 2 8 2 3 8 3 4 8 4 5 8 5 6 8 6 7 8 7 8 8 8
17
In the first sample all the numbers written on the cards are equal, so you can't take more than one card, otherwise you'll violate the first condition.
题目大意:
给你一个长度为N的一个序列,需要我们找到一个最长的序列,保证每个元素(1~8)的个数之前的绝对值差小于等于1,而且对应选出来的序列中,需要保证相同的元素是连续的。
思路(补题真好玩系列0.0):思路来源于(http://www.cnblogs.com/Saurus/p/6183721.html);
1、首先我们很容易想到状压,我们肯定是状压8个数字的状态,其中1表示这个位子上的数已经选完了,0表示没有选完,那么我们在想dp数组的维度的时候,以及初算时间复杂度的时候,发现这个出现的次数一直是一个很难处理的点,那么我们首先对这个出现的次数进行优化:
①我们可以通过枚举来dp,每次枚举一个出现的次数,进行最大值的维护 ,我们不难想到:对应这个出现的次数越多,结果就可能越长,那么其具有单调性。
②对于可以枚举的具有单调性存在的变量,我们可以通过二分查找来进行优化。
2、那么我们每一次二分枚举出的当前值mid,表示本次二分枚举出来每个数将要出现的次数。
①对于当前值mid,每种数字出现的次数要么是mid次,要么是mid-1次。
②考虑dp,我们设定dp【i】【j】表示dp过程进行到第i位,对应j状态下的最多出现mid次的数字的个数。
③那么考虑状态转移方程:
如果我们直接暴力的话肯定时间复杂度是吃不消的,那么我们考虑调用一个vector<int >mp;mp【i】用于存储数字i出现的各个位子,我们按照升序排列存储。
那么接下来:
④维护好每次二分情况的最大值即可。
Ac代码:
#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>using namespace std;int a[100050];int ans,n;vector<int >mp[1050];int cur[1050];int dp[1050][1<<8];int Slove(int mid){ int end=(1<<8); for(int i=1;i<=8;i++)cur[i]=0; memset(dp,-1,sizeof(dp)); dp[1][0]=0; for(int i=1;i<=n;i++) { for(int j=0;j<end;j++) { if(dp[i][j]<0)continue; for(int k=1;k<=8;k++) { if(j &(1<<(k-1)))continue; if(mp[k].size()-cur[k]<mid-1)continue; dp[mp[k][cur[k]+mid-2]][j|(1<<(k-1))]=max( dp[mp[k][cur[k]+mid-2]][j+(1<<(k-1))],dp[i][j]); if(mp[k].size()-cur[k]<mid)continue; dp[mp[k][cur[k]+mid-1]][j|(1<<(k-1))]=max( dp[mp[k][cur[k]+mid-1]][j+(1<<(k-1))],dp[i][j]+1); } } cur[a[i]]++; } int sum=-0x3f3f3f3f; for(int i=1;i<=n;i++)sum=max(sum,dp[i][(1<<8)-1]); if(sum<=0)return 0; ans=max(ans,sum*mid+(8-sum)*(mid-1)); return 1;}int main(){ while(~scanf("%d",&n)) { for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++)mp[a[i]].push_back(i); int l=2,r=n; ans=0; while(r-l>=0) { int mid=(l+r)/2; if(Slove(mid)==1) { l=mid+1; } else r=mid-1; } if(ans==0) { for(int i=1;i<=8;i++)if(mp[i].size()>0)ans++; } printf("%d\n",ans); }}
- Codeforces Round #384 (Div. 2)E.Vladik and cards【二分+状压dp】
- Codeforces Round #384 (Div. 2)E.Vladik and cards【二分+状压dp】(未敲)
- E. Vladik and cards Codeforces Round #384 (Div. 2) 好题 二分+(贪心+状态压缩DP)判断
- Codeforces Round #384 (Div. 2) E. Vladik and cards
- Codeforces Round #384 (Div. 2) E. Vladik and cards
- [DP]Codeforces 743E Vladik and cards
- 【二分+乱搞】Codeforces 743E Vladik and cards
- codeForces-743E Vladik and cards(状压+记忆化搜索+二分)
- Codeforces Round #384(Div. 2)C. Vladik and fractions【数学】
- Codeforces Round #384 (Div. 2) A Vladik and flights
- Codeforces Round #384 (Div. 2) C Vladik and fractions
- Codeforces Round #384 (Div. 2)-C. Vladik and fractions
- Codeforces Round #384 (Div. 2) C. Vladik and fractions
- Codeforces Round #384 (Div. 2) 743A Vladik and flights
- Codeforces Round #384 (Div. 2) 743C Vladik and fractions
- Codeforces Round #384 (Div. 2) C. Vladik and fractions
- Codeforces Round #384 (Div. 2) A. Vladik and flights
- [线段树] Codeforces 811E Round #416 (Div. 2) E. Vladik and Entertaining Flags
- word使用技巧(wps)
- NTP配置实践
- 【小QのSpringBoot-翻译】Spring Boot官方参考指南-第一部分 Spring Boot文档
- 子查询作为数据源时是否需要表别名
- HDU 3282-Running Median
- Codeforces Round #384 (Div. 2)E.Vladik and cards【二分+状压dp】
- maven学习总结
- 指针笔记
- C 操作字符串/字符/字节相关的库函数
- 流量矿石:经历九死一生,曾获王欣亲自嘉奖,被5亿快播用户追捧
- React Reflux
- Js中级--DOM事件流
- 使用栈来实现括号匹配
- 爱情:当你一个人熬过了所有的苦(城市很大,梦想渺小)