DP。。。。。
5 2 25 25 32 32 25 5 1 25 26 25 26 25 0 0
Case 1: 2 Case 2: 3
#include <iostream> #include <cstring> #include <cstdio> using namespace std; #define prt(k) cout<<#k" = "<<k<<endl const int N = 105; const int inf = 0x3f3f3f3f; int dp[2][265][N][10]; ///pos, mask, k books, last int n, lim; int a[N]; inline void Min(int &a, int b) { a=min(a,b); } int num[324]; int main() { int ca = 1; num[0]=0; for(int i=1;i<256;i++) num[i]=num[i>>1]+(i&1); while(cin>>n>>lim, n) { int cnt[N]; memset(cnt,0,sizeof cnt); for(int i=0;i<n;i++) cin>>a[i],a[i]-=25; memset(dp, 63, sizeof dp); int total = 0; for(int i=0;i<n;i++) total |= (1<<a[i]); dp[0][0][0][8] = 0; int now = 0; for(int i=0;i<n;i++) { for(int mask=0;mask<(1<<8);mask++) ///每种书当前有没有全部拿出来 { for(int k=0;k<=lim&&k<=i;k++) ///take books----已经拿了多少书 { for(int j=0;j<=8;j++) ///last book --- 序列中上一本书高度 { int t=dp[now][mask][k][j]; if(t>=inf) continue; /// printf("dp[%d][%d][%d] = %d\n", mask, k, j, t); ///不把书拿出来 int add=0; if(j==a[i]) add=0; else add=1; Min(dp[1-now][mask|(1<<a[i])][k][a[i]], t+add); ///这本书留下来,有了这种书 ///take i book 把书拿出来 if(k==lim) continue; Min(dp[1-now][mask][k+1][j], t); } } } memset(dp[now], 63, sizeof dp[now]); now = 1 - now; } int ans=inf; for(int s=0;s<256;s++) { for(int k=0;k<=lim;k++) { for(int j=0;j<=8;j++) { int t=dp[now][s][k][j]; if(t>=inf) continue; ans=min(ans, dp[now][s][k][j] + num[total^s]); /// printf("dp[%d][%d][%d] = %d\n", s, k, j, dp[now][s][k][j]); } } } printf("Case %d: %d\n\n", ca++, ans); } return 0; } /** 5 2 25 25 32 32 25 5 1 25 26 25 26 25 5 1 25 30 25 30 25 5 2 25 30 25 30 25 5 5 25 30 25 30 25 0 0 */