POJ 2978

题意:给定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 }

你可能感兴趣的:(poj)