我的dp水平还想不透 压缩dp 更不用说 做出来了。
对于这个题。 用二进制保存当前状态。 前提是发现规律。 只有当递减序列的时候才可能出现压缩。
用 d【i】【j】 保存 到了第 i个数的时候 状态为j的分数最大值。j状态也就是说 如果到了这个位置有 16 8 4 那就二进制表示成 1 1 1 0 0 = 28
初始化 d的时候 用 两层 for
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MAXN 1000000+10
#define INF (1<<30)
#define mod 123456789
double eps = 1e-10;
int d[500+10][9000];
int a[500+10] = {0};
int main (){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
}
for(int i = 0; i <= n; i++){
for(int j = 0; j < (9000); j++)
d[i][j] = -1;
}
d[0][0] = 0;
for(int i = 0; i <= n-1; i++){
for(int j = 0; j < 9000; j++){
if(d[i][j] == -1)
continue;
d[i+1][j] = max(d[i+1][j], d[i][j]); // 不选这个数
if((a[i+1]-1)&j)
d[i+1][a[i+1]] = max(d[i+1][a[i+1]],d[i][j]+a[i+1]); // 非递减序列的时候 以当前序列为状态
else if(a[i+1]&j){ // 当递减序列的时候 如果 可以并列。
int t = a[i+1];int score = 0;
while(t&j){
t = t<<1;
score += t;
}
d[i+1][a[i+1]+j] = max(d[i+1][a[i+1]+j], d[i][j]+score+a[i+1]);
}
else // 其他情况
d[i+1][j+a[i+1]] = max(d[i+1][a[i+1]+j], d[i][j]+a[i+1]);
}
}
int M = 0;
for(int i = 0; i < 9000; i++)
M = max(M, d[n][i]);
printf("%d\n",M);
}
return 0;
}

本文介绍了一种使用二进制状态压缩的动态规划方法,通过一个具体题目解释了如何利用递减序列进行状态压缩,减少状态空间,从而提高算法效率。文章提供了一个C++实现示例。
&spm=1001.2101.3001.5002&articleId=41176543&d=1&t=3&u=f05ec4cf55f448348a0823630f0b0a55)
620

被折叠的 条评论
为什么被折叠?



