Bubu的書架亂成一團了!幫他一下吧!
他的書架上一共有n本書。我們定義混亂值是連續相同高度書本的段數。例如,如果書的高度是30,30,31,31,32,那麼混亂值爲3,30,32,32,31的混亂度也是3,但31,32,31,32,31的混亂度是5,這實在是太亂了。
Bubu想盡可能地減少混亂度,但他有點累了,所以他決定最多取出k本書,再隨意將它們放到書架上。你能幫助他嗎?
考慮取出一本書把其認爲是刪掉這本書,因爲總有辦法使其不會影響到後面的取書過程
特殊的是如果將一種書全部刪掉,那麼應該還是會有1的混亂度
如果考慮方式爲如何刪書,那麼這個過程實在複雜
如果考慮最後剩下的書,那麼複雜度是妥妥的
但是仔細的想一下,會發現,考慮最後剩下的書時,並不是前面所有的狀態都對現在的狀態會有影響
即如果一本書隔得較遠,則與你當前這本書沒有多大關係,在保證所有的狀態會被考慮在內的情況下,考慮狀態壓縮
設表示前本書,刪掉了本,剩下書的種類的集合爲,上一本沒有被刪的書的種類是
考慮第本書
- 若刪掉這本書,則有
- 若保留這本書,則有
最後的時候回來考慮剩下的書的種類集合,如果原本所有書的種類集合有一種書,現在沒有了,那麼我們就多減了一個1,加回來就是
/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年10月04日 星期五 08時36分03秒
*******************************/
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cstring>
#define inf 0x7f7f7f7f
using namespace std;
const int maxn = 111;
const int lim = 256;
//{{{cin
struct IO{
template<typename T>
IO & operator>>(T&res){
res=0;
bool flag=false;
char ch;
while((ch=getchar())>'9'||ch<'0') flag|=ch=='-';
while(ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
if (flag) res=~res+1;
return *this;
}
}cin;
//}}}
int n,k,cas;
int h[maxn],one[lim+5];
int f[2][maxn][lim+5][11];
bool now,pre;
//f[i][j][k][l] 前i本書選了j本書,存在的書的種類集合爲k,上一本書爲l
int main()
{
for (int i=0;i<lim;++i){
for (int j=0;j<8;++j)
if (i&(1<<j)) ++one[i];
}
while (true){
cin>>n>>k;
if (n+k==0) break;
int S=0,mh=0;
for (int i=1;i<=n;++i){
cin>>h[i];
h[i]-=25;
S|=1<<h[i];
mh=max(mh,h[i]);
}
++mh;
memset(f[0],0x7f,sizeof(f[0]));
now=0;
f[0][0][1<<h[1]][h[1]]=1;
f[0][1][0][mh]=0;
for (int i=2;i<=n;++i){
now^=1,pre=!now;
memset(f[now],0x7f,sizeof(f[now]));
for (int j=0;j<=k;++j){
for (int s=0;s<=S;++s)
for (int l=0;l<=mh;++l)
if (f[pre][j][s][l]!=inf){
f[now][j][s|(1<<h[i])][h[i]]=min(f[now][j][s|(1<<h[i])][h[i]],f[pre][j][s][l]+(h[i]==l?0:1));
f[now][j+1][s][l]=min(f[now][j+1][s][l],f[pre][j][s][l]);
}
}
}
int ans=inf;
for (int j=0;j<=k;++j)
for (int s=0;s<=S;++s)
for (int l=0;l<mh;++l)
if (f[now][j][s][l]!=inf){
int take=S^s;
ans=min(ans,f[now][j][s][l]+one[take]);
}
printf("Case %d: %d\n\n",++cas,ans);
}
return 0;
}
如有哪裏講得不是很明白或是有錯誤,歡迎指正
如您喜歡的話不妨點個贊收藏一下吧