题意:给定m个数字,有k种,求从中扔掉最少多少个,使得最后相同种类的数字都在一起。
题解:状态压缩DP,并不算太复杂,dp[i][j][mask]代表前i个珠子,以j结尾,且前面已经出现了mask珠子的最小代价。
View Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int dp[105][6][40]; 6 const int inf=0x3f3f3f3f; 7 int main() 8 { 9 int n,k; 10 while(scanf("%d%d",&n,&k),n||k) 11 { 12 memset(dp,0x3f,sizeof(dp)); 13 dp[0][0][0]=0; 14 int ma=1<<k,ans; 15 for(int i=1;i<=n;i++) 16 { 17 int tp; 18 scanf("%d",&tp); 19 for(int j=0;j<ma;j++) 20 { 21 for(int t=0;t<=k;t++) 22 { 23 if(dp[i-1][t][j]!=inf) 24 { 25 if(t==0) 26 { 27 dp[i][0][0]=dp[i-1][t][j]+1; 28 dp[i][tp][(1<<(tp-1))]=dp[i-1][t][j]; 29 } 30 else if(t!=tp) 31 { 32 dp[i][t][j]=min(dp[i][t][j],dp[i-1][t][j]+1); 33 if(!(j&(1<<(tp-1)))) 34 dp[i][tp][j|(1<<(tp-1))]=min(dp[i][tp][j|(1<<(tp-1))],dp[i-1][t][j]); 35 } 36 else 37 dp[i][t][j]=min(dp[i][t][j],dp[i-1][t][j]); 38 } 39 40 } 41 } 42 } 43 ans=inf; 44 for(int i=1;i<=k;i++) 45 for(int j=0;j<ma;j++) 46 ans=min(ans,dp[n][i][j]); 47 printf("%d\n",ans); 48 } 49 return 0; 50 }