等价转换:
从有n本书的书堆里面抽取k本书,再插入书堆里面,计算书的杂乱度
等价于
向空的书架上按给出的顺序放上n本书,再从中抽取k本书,然后插入书堆里面,计算书的杂乱度
等价于
向空的书架上按给出的顺序放上n-k本书,然后再放上k本书,想放哪放哪,计算书的杂乱度。
显然第一阶段放n-k本书,就是一个简单的背包+集合动态规划。
对于每一本书,可以选也可以不选。
dp[ind][v][last][s]表示考虑了前面ind本书,其中有v本没有放进去,last表示最后一本的高度,s表示选取了哪些高度的
书。
第二阶段:
对于没有放进去的书,如果书架中已经有与之高度相同的书,那么放到那本书旁边,杂乱度不变。
如果没有,随便放,但要求:和它同高度没放进去的书要和它放在一起,杂乱度+1。
/**==========================================
* This is a solution for ACM/ICPC problem
*
* @source:uvaLive 4490 - Help Bubu (Wuhan 2009)
* @type: dp
* @author: wust_ysk
* @blog: http://blog.csdn.net/yskyskyer123
* @email: 2530094312@qq.com
*===========================================*/
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define REP(i,n) for(int i=0 ;i<(n) ;i++)
#define ysk(x) (1<<(x))
using namespace std;
typedef long long ll;
const int INF =0x3f3f3f3f;
const int maxn= 100 ;
int n,V,all,kase=0;
int h[maxn+5];
const int N=8;
const int ed=ysk(N)-1;
int dp[2][N+2][maxn+5][ed+3];//[当前阶段][最后一个是谁][几个没选][选了哪些种];
int cal(int s)
{
int ans=0;
for(int i=0;i<N;i++) if(all&ysk(i))
{
int x=s&ysk(i);
int y=all&ysk(i);
ans+= x^y?1:0;//我艹,当初写成了x^y,wa了好多发
}
return ans;
}
void update(int & ans ,int ret)
{
if(ans<0||ret<ans) ans=ret;
}
void work()
{
memset(dp,-1,sizeof dp);
int now=0,pre=1;
dp[now][0][0][0]=0;
for(int i=1;i<=n;i++)
{
now^=1;
pre^=1;
for(int last=0;last<=N;last++) if(!last || all&ysk(last-1)) //最后一个是谁
{
for(int v=0;v<=V;v++ )//几个没选
{
for(int s=0;s<=ed;s++) if(~dp[pre][last][v][s])//选了哪些种
{
int x=h[i]-25;
if(v+1<=V)
{
update(dp[now][last][v+1][s],dp[pre][last][v][s] );
}
int ret= (last==x+1) ?dp[pre][last][v][s]:dp[pre][last][v][s]+1;
update( dp[now][x+1][v][s|ysk(x)],ret );
}
}
}
memset(dp[pre],-1,sizeof dp[pre]);//
}
int ans=n;
for(int last=0;last<=N;last++) if(!last || all&ysk(last-1))
{
for(int v=0;v<=V;v++)
{
for(int s=0;s<=ed;s++) if(~dp[now][last][v][s])
{
ans=min(ans,cal(s)+dp[now][last][v][s]);
}
}
}
printf("Case %d: %d\n\n",++kase,ans);
}
int main()
{
while(~scanf("%d%d",&n,&V)&&(n||V))
{
all=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&h[i]);
all|= ysk(h[i]-25);
}
work();
}
return 0;
}