您的位置:首页 > 其它

uvalive4490(状态压缩 + dp)

2016-04-26 22:21 375 查看
题目大意:

从左到右给出n本数的高度和最多可以抽取的书本的数量k,如果书本与相邻的书本的高度不相同的话就是一个段,段越多混乱度就越高。求最低的混乱度。

思路:

dp[i][j][s][end]表示前i本书操作了j次,剩下的书的状态为s,最后一本书是end的最低的混乱度。

那么对于一本书有两种情况:

1. 跟其前面的书籍的高度是一样的

那么dp[i][j][s][end] = min(dp[i][j][s][end],dp[i - 1][j][s][end]);

2. 跟其前面的书籍的高度是不一样

(1)抽取这本书出来

那么dp[i][j + 1][s][end] = min(dp[i][j + 1][s][end],dp[i - 1][j][s][end]);

为什么会等于dp[i - 1][j][s][end]?

因为你将第i本数抽取出来了实行了j + 1次操作相当于你对第i - 1本书实行了j次操作。

(2)不抽取这本书

那么dp[i][j][s | (1 << num)][num] = min(dp[i][j][s|(1 << num)][num],dp[i][j][s][end] + 1);

代码:

#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>
const int maxn = 1 << 8;
const int INF = 0x3f3f3f3f;
const int maxm = 110;

int dp[2][maxm][maxn][10],n,k;//由于只有前后操作所以2就足够了 利用滚动数组
int rec[1 << 8];

void init() {
for(int i = 0; i < (1 << 8); i++) {//记录每个状态的书本最多有多少种段数 主要是用于抽取出来的书籍重新插入 每插入一次就增加一个段 如果留下来的有这种类就不用增加
rec[i] = 0;
for(int j = 0; j < 8; j++)
if(i &(1 << j))
rec[i]++;
}
}
int main() {
int T = 0;
init();
while(scanf("%d %d",&n,&k)  == 2 &&n && k) {
int S = 0;
int num,now,pre;
memset(dp[0],INF,sizeof(dp[0]));

for(int i = 0; i < n; i++) {
scanf("%d",&num);
num -= 25;
pre = i & 1;//滚动数组的巧妙用法 只需要考虑前后的时候可以使用
now = !pre;
memset(dp[now],INF,sizeof(dp[now]));
dp[now][i][(1 << num)][num] = 1;
for(int j = 0; j <= min(i,k); j++)
for(int s = S;s;s = (s - 1) & S) {
for(int end = 0;(1 << end) <= s; end ++) {
if(dp[pre][j][s][end] == INF)
continue;
if(end == num)
dp[now][j][s][end] = min(dp[now][j][s][end],dp[pre][j][s][end]);
else {
dp[now][j + 1][s][end] = min(dp[now][j + 1][s][end],dp[pre][j][s][end]);
dp[now][j][s |(1 << num)][num] = min(dp[now][j][s |(1 << num)][num],dp[pre][j][s][end] + 1);
}
}
}
S = S |(1 << num);//记录下总的种类数

}
int ans = INF;
for(int j = 0; j <= k; j++) {
for(int s = S;s;s = (s - 1)&S) {
for(int end = 0;(1 << end) <= s;end++) {
if(dp[n & 1][j][s][end] != INF ){
ans = min(ans,dp[n & 1][j][s][end] + rec[S^s]);//S^s记录的是被抽出来的在留下的种类中不存在的种类
//cout << ans <<endl;
}
}
}
}
printf("Case %d: %d\n\n",++T,ans);

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: