Help bubu
很有趣的一道dp题
我们先换个角度看这道题
我们可以把他看作,最多取出k,然后把一样的放一起,在放到一个地方去,使得答案最小
我们考虑dp
设\(f[i][j][o][la]\)表示第\(i\)本书,取了\(j\)本,然后没有取出的书种类状态\(o\),最后一个没有取出的为\(la\)的答案
那么就有状态转换方程
当前这本不取出
\(f[i][j][o][la]=min:{f[i-1][j][o|(1<<a[i])][a[i]]+[a[i]!=la]}\)
否则
\(f[i][j][o][la]=min:{f[i-1][j-1][o][la]+((o\space and \space((1<<a[i])) or\space is[i][a[i]])?0:1)}\)
其中\(is[i][j]\)表示位置\(i\)处\(j\)为不为最后一个
#include<bits/stdc++.h>
#define N 511
#define K 111
#define M 9
using namespace std;
int n,k,a[N];
bool is[N][M];
int f[2][K][1<<M][M];
inline void work(int t){
scanf("%d%d",&n,&k);
if(!n&&!k)exit(0);
memset(is,0,sizeof(is));
int i,j,o,la;
for(i=1;i<=n;++i){
scanf("%d",&a[i]);
a[i]-=25;
}
for(i=1;i<=n;++i)
for(j=i+1;j<=n;++j)
is[i][a[j]]=1;
memset(f[0],63,sizeof(f[0]));
f[0][0][0][8]=0;
for(i=1;i<=n;++i){
memset(f[i&1],63,sizeof(f[i&1]));
for(j=0;j<=k;++j)
for(o=0;o<(1<<8);++o)
for(la=0;la<=8;++la)
if(la==8||o&(1<<la)){
f[i&1][j][o|(1<<a[i])][a[i]]=min(f[(i&1)^1][j][o][la]+(a[i]!=la),f[i&1][j][o|(1<<a[i])][a[i]]);
if(j>=1)f[i&1][j][o][la]=min(f[i&1][j][o][la],f[(i&1)^1][j-1][o][la]+(((o&(1<<a[i]))||is[i][a[i]])?0:1));
}
}
int ans(1e9);
for(j=0;j<=k;++j)
for(o=0;o<(1<<8);++o)
for(la=0;la<=8;++la)if(la==8||o&(1<<la))ans=min(ans,f[n&1][j][o][la]);
printf("Case %d: %d\n\n",t,ans);
}
int main( ){
int i;
for(i=1;;++i)
work(i);
}