状压DP——hihoCoder 1044
2017-02-12 17:04
411 查看
题目链接:https://hihocoder.com/problemset/problem/1044
题意:给出一个数组A,长度为N,表示每个位置i含有A[i]数量的垃圾,求选取一些位置,在满足连续M个位置中被选中的位置不超过Q个的条件下使得这些被选中的位置对应的垃圾数量的总和最大,输出这个最大数量
分析:我们很容易得出一个转移方程:DP[i]→DP[i+1] 表示前i个位置中满足条件的最大垃圾数量 推出 前 i+1 个位置中满足条件的最大垃圾数量。但是我们推的过程中,需要得知前一个状态的信息:比如第 i−M+1 是否被选中,以及区间 [i−M+1,i] 中一共被选中了多少个位置,才能推出下一个状态。
状态表示:我们可以用一个长度为M的二进制串1010101..表示一个区间M的位置选取情况,其中1表示选取,0表示未选。然后我们可以预处理用一个数组B(下标为二进制串对应的十进制数j)来存取每一个二进制数含有多少个1方便之后查询每一个区间M内选取的1的个数。
状态转移:
AC代码:
题意:给出一个数组A,长度为N,表示每个位置i含有A[i]数量的垃圾,求选取一些位置,在满足连续M个位置中被选中的位置不超过Q个的条件下使得这些被选中的位置对应的垃圾数量的总和最大,输出这个最大数量
分析:我们很容易得出一个转移方程:DP[i]→DP[i+1] 表示前i个位置中满足条件的最大垃圾数量 推出 前 i+1 个位置中满足条件的最大垃圾数量。但是我们推的过程中,需要得知前一个状态的信息:比如第 i−M+1 是否被选中,以及区间 [i−M+1,i] 中一共被选中了多少个位置,才能推出下一个状态。
状态表示:我们可以用一个长度为M的二进制串1010101..表示一个区间M的位置选取情况,其中1表示选取,0表示未选。然后我们可以预处理用一个数组B(下标为二进制串对应的十进制数j)来存取每一个二进制数含有多少个1方便之后查询每一个区间M内选取的1的个数。
状态转移:
if(B[j] > Q) DP[i][j] = DP[i][j+1] = 0 else if(B[j] == Q) DP[i][j] = j>>1再前面补0或者1 的情况下符合少于Q的状态里最大的垃圾数量 DP[i][j+1] = 0 else DP[i][j] = j>>1再前面补0或者1 的情况下符合少于Q的状态里最大的垃圾数量 DP[i][j+1] = j>>1再前面补0或者1 的情况下符合少于Q的状态里最大的垃圾数量 + A[i]
AC代码:
/************************************************************************* > File Name: test.cpp > Author: Akira > Mail: qaq.febr2.qaq@gmail.com ************************************************************************/ #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cmath> #include <vector> #include <set> #include <list> #include <ctime> typedef long long LL; typedef unsigned long long ULL; typedef long double LD; #define MST(a,b) memset(a,b,sizeof(a)) #define CLR(a) MST(a,0) #define Sqr(a) ((a)*(a)) using namespace std; #define MaxN 100000 #define MaxM MaxN*10 #define INF 0x3f3f3f3f #define bug cout<<88888888<<endl; #define MIN(x,y) (x<y?x:y) #define MAX(x,y) (x>y?x:y) // 快速读入输出 template<typename _> inline void scan(_& t) { int c; while((c = getchar()) < '0' || c > '9'); t = c - '0'; while((c = getchar()) >= '0' && c <= '9') t = t * 10 + c - '0'; } template<typename _> inline void print(_ x) { int len = 0, p[20]; if(x < 0) putchar('-'), x = -x; while(x) p[++len] = x % 10, x /= 10; if(!len) p[++len] = 0; while(len) putchar(p[len--] + '0'); } int N,M,Q; int A[MaxN]; int DP[2][1<<10]; int num[1<<10]; int get(int pos, int flag) { int v = pos>>1; if(num[v]<Q) return MAX(DP[flag][v+(1<<(M-1))], DP[flag][v]); if(num[v]==Q) return DP[flag][v]; } int cal(int x) { int ans = 0; while(x) { if(x&1) ans+=1; x>>=1; } return ans; } void solve() { int len = 1<<M; for(int i=0;i<len;i++) num[i] = cal(i); int flag = 0; for(int i=0;i<N;i++) { for(int j=0;j<len;j+=2) { if(num[j]>Q) { DP[flag][j] = DP[flag][j+1] = 0; continue; } else if(num[j] == Q) { DP[flag][j] = get(j, flag^1); DP[flag][j+1] = 0; continue; } else { DP[flag][j] = DP[flag][j+1] = get(j, flag^1); DP[flag][j+1] += A[i]; } } flag^=1; } int ans = 0; for(int i=0;i<len;i++) ans = MAX(ans, DP[flag^1][i]); print(ans); cout << endl; } int main() { scan(N); scan(M); scan(Q); for(int i=0;i<N;i++) scan(A[i]); solve(); //system("pause"); }
相关文章推荐
- Hihocoder 1044 DP状态压缩
- hihocoder 1044 状态压缩·一 (状态dp)
- HihoCoder - 1044 状态压缩·一 状态压缩dp
- hihocoder 1044 状态压缩dp
- hihocoder 1044 (状压dp)
- hihoCoder 1044 状态压缩·一 (状压dp)
- hihoCoder 1044 : 状态压缩·一 状压dp
- hihoCoder1044 简单状压DP
- hihocoder 1044 动态规划 状态压缩
- lightoj 1044 Palindrome Partitioning(dp)
- [DP] Luogu1044 栈
- 【DP】hihocoder1596 Beautiful Sequence
- 【DP?】hihocoder1526 序列的值
- 【HIHOCODER 1526】 序列的值(二进制DP)
- Hihocoder 1580 Matrix【思维+Dp+RMQ】
- hihoCoder 1476 矩形计数 dp
- 1044 - Palindrome Partitioning(记忆化DP)
- [Offer收割]编程练习赛2 hihocoder 1272 买零食 (DFS 或 dp 水题)
- [hihoCoder挑战赛24](贪心)(期望DP)(后缀自动机)
- Lightoj 1044 DP