uva12235 - Help Bubu 四维状态压缩DP

Bubu's bookshelf is in a mess! Help him!

There are n books on his bookshelf. We define the mess value to be the number of segments ofconsecutive equal-height books. For example, if the book heights are 30, 30, 31, 31, 32, the mess value is 3, that of 30, 32, 32, 31 is also 3, but the mess value of 31, 32, 31, 32, 31 is 5 -- it's indeed in a mess!

Bubu wants to reduce the mess value as much as possible, but he's a little bit tired, so he decided to take out at mostk books, then put them back somewhere in the shelf. Could you help him?

Input 

There will be at most 20 test cases. Each case begins with two positive integersn andk (1kn100), the total number of books, and the maximum number of books to take out. The next line containsn integers, the heights of each book, from left to right. Each height is an integer between 25 and 32, inclusive. The last test case is followed byn = k = 0, which should not be processed.

Output 

For each test case, print the case number and the minimal final mess value. Print a blank line after the output of each test case.

Sample Input 

5 2 
25 25 32 32 25 
5 1 
25 26 25 26 25 
0 0

Sample Output 

Case 1: 2 

Case 2: 3

  看了别人的。。这个题能做出来的人真是大神。。

  N本书,吧相邻高度相同的看成一个片段,混乱程度为片段数。可以取走K本书,再插入回去。输出整理后混乱程度的最小值。

  先算出取走n本书的各种剩余状态的最小混乱值,插入时只要在剩余的书里没有要插入的书的这个高度,混乱度肯定就要加1。

  问题是怎么算取走n本书的各种剩余状态的最小混乱值。

  设dp[i][j][s][k]为前i本书,取走j本,剩余的书的状态为s,剩余的书的最后一本高度为k的最小混乱值。

  设第i本书高度为t,dp[i][i-1][1<<t][t]=1,这个是跟i之前的书状态没有关系的,只由第i本书决定。剩下的状态就跟i之前的有关系了。

  若dp[i-1][j][s][k]存在:

  如果 t=k, dp[i][j][s][k]=min(dp[i][j][s][k],dp[i-1][j][s][k])

  否则 不取走第i本书 dp[i][j][s|(1<<t)][t]=min(dp[i][j][s|(1<<t)][t],dp[i-1][j][s][k]+1)。

          取走第i本书 dp[i][j+1][s][k]=min(dp[i][j+1][s][k],dp[i-1][j][s][k])

  最后只要找dp[N][j][s][k]存在的情况加上放回增加的混乱度的最小值就行了。

  用滚动数组做省空间。

#include<cstring>
#include<cstdio>
#include<iostream>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#define INF 0x3f3f3f3f
#define MAXN 110
#define MAXM 8
using namespace std;
int N,K;
int dp[2][MAXN][1<<MAXM][MAXM];
int main(){
    freopen("in.txt","r",stdin);
    int cas=0;
    while(scanf("%d%d",&N,&K),N||K){
        int pre,now=0,t,all=0;
        memset(dp[now],INF,sizeof(dp[now]));
        for(int i=0;i<N;i++){
            scanf("%d",&t);
            t-=25;
            pre=now;
            now=!now;
            memset(dp[now],INF,sizeof(dp[now]));
            dp[now][i][1<<t][t]=1;
            for(int j=0;j<=min(i,K);j++)
                for(int s=all;s;s=(s-1)&all)
                    for(int k=0;(1<<k)<=s;k++) if(dp[pre][j][s][k]!=INF){
                        if(t==k) dp[now][j][s][t]=min(dp[now][j][s][t],dp[pre][j][s][k]);
                        else{
                            dp[now][j][s|(1<<t)][t]=min(dp[now][j][s|(1<<t)][t],dp[pre][j][s][k]+1);
                            dp[now][j+1][s][k]=min(dp[now][j+1][s][k],dp[pre][j][s][k]);
                        }
                    }
            all|=(1<<t);
        }
        int ans=INF;
        for(int i=0;i<=K;i++)
            for(int s=all;s;s=(s-1)&all)
                for(int k=0;(1<<k)<=s;k++) if(dp[now][i][s][k]!=INF){
                    int cnt=0;
                    for(int s0=s^all;s0;s0>>=1) if(s0&1) cnt++;
                    ans=min(ans,cnt+dp[now][i][s][k]);
                }
        printf("Case %d: %d\n\n",++cas,ans);
    }
    return 0;
}



你可能感兴趣的:(uva12235 - Help Bubu 四维状态压缩DP)