帮助_NOI导刊2010提高(03)
题目描述
Bubu的书架乱成一团了!帮他一下吧!
他的书架上一共有n本书。我们定义混乱值是连续相同高度书本的段数。例如,如果书的高度是30,30,31,31,32,那么混乱值为3,30,32,32,31的混乱度也是3,但31,32,31,32,31的混乱度是5-,这实在是太乱了。
Bubu想尽可能地减少混乱度,但他有点累了,所以他决定最多取出k本书,再随意将它们放到书架上。你能帮助他吗?
输入格式
最多会有20组测试数据。每组测试数据开头为两个整数n,k(l≤k≤n≤100),表示总共有n本书,最多可以进行k次搬书操作。接下来一行有n个整数,表示每本书的高度,从左到右。每本书的高度是25到32间的整数。最后一组数据后有一行n=k=0。
输出格式
对于每一组数据,输出Case标号和最终最小的混乱度。在每组数据后打印一个空行。
输入输出样例
输入 #1
5 2 25 25 32 32 25 5 1 25 26 25 26 25 0 0
输出 #1
Case 1:2 Case 2:3
分析:
本题给定的数据显然让我们想到状态压缩DP,那么我们可以设计状态f[i][j][s][l],表示前i个选了j个状态为s最后一个为l所能得到最小的混乱度,然后进行状态转移即可。
然后发现我的代码最后一个点超时,死活过不去。。。所以我开了O2。。。
CODE:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 using namespace std; 7 const int M=120; 8 const int N=265; 9 int f[2][M][N][15]; 10 int a[M],b[N]; 11 int n,k,cnt; 12 int get(){ 13 char c=getchar(); 14 int res=0,f=1; 15 while (c>'9'||c<'0'){ 16 if (c=='-') f=-1; 17 c=getchar(); 18 } 19 while (c<='9'&&c>='0'){ 20 res=(res<<3)+(res<<1)+c-'0'; 21 c=getchar(); 22 } 23 return res*f; 24 } 25 int main(){ 26 for(int i=0;i<(1<<8);i++){ 27 b[i]=0; 28 for(int j=0;j<8;j++) 29 if(i&(1<<j)) b[i]++; 30 } 31 while(~scanf("%d%d",&n,&k)&&(n+k)){ 32 int S=0,maxn=0; 33 for(int i=1;i<=n;i++){ 34 a[i]=get(); 35 a[i]-=25; 36 S=S|(1<<a[i]); 37 maxn=max(maxn,a[i]); 38 } 39 maxn++; 40 memset(f[0],120,sizeof(f[0])); 41 f[0][1][0][maxn]=0; 42 f[0][0][(1<<a[1])][a[1]]=1; 43 int cur=0,pre=0; 44 for(int i=1;i<n;i++){ 45 cur=pre^1; 46 memset(f[cur],120,sizeof(f[cur])); 47 for(int j=0;j<=k;j++){ 48 for(int s=0;s<=S;s++){ 49 for(int l=0;l<=maxn;l++){ 50 if(f[pre][j][s][l]==120) continue; 51 f[cur][j][s|(1<<a[i+1])][a[i+1]]=min(f[cur][j][s|(1<<a[i+1])][a[i+1]],f[pre][j][s][l]+(a[i+1]==l?0:1)); 52 f[cur][j+1][s][l]=min(f[cur][j][s][l],f[pre][j][s][l]); 53 } 54 } 55 } 56 pre=cur; 57 } 58 int ans=120; 59 for(int j=0;j<=k;j++){ 60 for(int s=0;s<=S;s++){ 61 for(int l=0;l<maxn;l++){ 62 if(f[cur][j][s][l]==120)continue; 63 int now=S^s; 64 ans=min(ans,f[cur][j][s][l]+b[now]); 65 } 66 } 67 } 68 printf("Case %d: %d\n\n",++cnt,ans); 69 } 70 return 0; 71 }