状态压缩的DP
压缩的状态是一个递减序列 如果序列非递减 则序列的前一部分(递减序列以前的数) 将不可能发生合并
所以当当前的数大于序列末的数,则可以直接将序列清空 保存当前的数字,这样可以保证序列中数的进入顺序也是一定的
zoj 数组访问越界了不反悔RE,坑在了数组开多大上面
#include<cstdio>
#include<cstring>
#include<iostream>
#include <algorithm>
#include<vector>
#include<stack>
using namespace std;
int dp[2][10100];
int a[510], n;
int getnewS(int now, int d, int* cc) {
while(d&now) {
*cc += d;
now ^= d;
d *= 2;
}
now ^= d;
*cc += d;
return now;
}
int main()
{
int t;
scanf("%d", &t);
while(t --) {
scanf("%d", &n);
for(int i = 1; i <= n; ++ i) {
scanf("%d", &a[i]);
}
memset(dp, 0, sizeof(dp));
int _max = 0, pre = 1, now = 0, dd = 0;
for(int i = 1; i <= n; ++ i) {
for(int j = 0; j <= _max; ++ j) {
dp[now][j] = dp[pre][j];
}
int cc = 0;
int ss = getnewS(0, a[i], &cc);
//printf("%d\n", cc);
dd = max(dd, ss);
dp[now][ss] = max(dp[now][ss], dp[pre][0]+cc);
for(int j = 2; j <= _max; ++ j) {
if(dp[pre][j]) {
cc = 0;
if(j&(a[i]-1)) {
dp[now][a[i]] = max(dp[now][a[i]], dp[pre][j]+a[i]);
continue;
}
int news = getnewS(j, a[i], &cc);
//printf("old: %d j: %d news: %d cc : %d\n", dp[pre][j], j, news, cc);
dp[now][news] = max(dp[now][news], dp[pre][j]+cc);
dd = max(dd, news);
}
}
pre ^= 1;
now ^= 1;
_max = dd;
}
int ans = 0;
for(int i = 0; i <= _max; ++ i) {
ans = max(ans, dp[pre][i]);
ans = max(ans, dp[now][i]);
}
printf("%d\n", ans);
}
return 0;
}