[POJ2978]ColoredStones
题目大意:有N≤100个石头排成一列,每个石头都有颜色编号≤5,求扔掉最少的石头,使得任意两个相同颜色的石头之间没有其他颜色的石头[多组数据]
题解:很明显的状态压缩DP,但我一开始竟然想到搜索剪枝(扔掉该扔的以后一定成了几个颜色的排列=5!,加点优化应该能过)
DP[i][j][k] 前 i 个 最后留下的石子颜色为 j 用 k 记录颜色的出现情况
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,ins[101],dp[101][6][32];
int main(){
freopen("DP.in","r",stdin);
freopen("DP.out","w",stdout);
int i,j,k,t,u,v,mm;
scanf("%d%d",&n,&m);
while(n){
mm=1<<m;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++){
scanf("%d",&ins[i]);
ins[i]--;
}
for(i=1;i<=n;i++) dp[i][ins[i]][1<<ins[i]]=1;
for(i=1;i<n;i++) for(j=0;j<m;j++) for(k=0;k<mm;k++) if(dp[i][j][k]){
t=dp[i][j][k];
u=ins[i+1];
v=1<<u;
if(u==j) dp[i+1][j][k]=max(dp[i+1][j][k],t+1);
else if(k&v) dp[i+1][j][k]=max(dp[i+1][j][k],t);
else{
dp[i+1][j][k]=max(dp[i+1][j][k],t);
dp[i+1][u][k|v]=max(dp[i+1][u][k|v],t+1);
}
}
k=1;
for(i=0;i<m;i++) for(j=0;j<mm;j++) k=max(k,dp[n][i][j]);
printf("%d\n",(n-k));
scanf("%d%d",&n,&m);
}
return 0;
}