题目描述见链接 .
提出的书可以放在任意位置, 所以可以先放在一边, 到最后处理,
设 表示处理到第 本书, 提出了 本书, 书架上最后一本书 高度 为 , 书架上的书高度状态为 时的 混乱值,
则决策有两个,
- 将 提出,
- 不将 提出, .
再考虑统计答案, .
其中 表示 二进制中 的个数 .
按以上方式更新状态时间复杂度 , 但若使用状态去更新状态, 时间复杂度 .
- 注意 要开 .
#include<bits/stdc++.h>
#define reg register
const int maxn = 105;
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
int N;
int K;
int num;
int Test_cnt;
int h[maxn];
int Mp[maxn];
int cnt[260];
int F[maxn][maxn][10][260];
int main(){
for(reg int i = 1; i < 260; i ++) cnt[i] = cnt[i ^ (i & -i)] + 1;
while((N = read()) && (K = read())){
memset(Mp, 0, sizeof Mp); num = 0;
for(reg int i = 1; i <= N; i ++){
h[i] = read()-24;
if(!Mp[h[i]]) Mp[h[i]] = ++ num;
h[i] = Mp[h[i]];
}
for(reg int i = 0; i <= N; i ++)
for(reg int j = 0; j <= K; j ++)
for(reg int k = 0; k <= num; k ++)
for(reg int s = 0; s < (1<<num); s ++) F[i][j][k][s] = 0x3f3f3f3f;
F[0][0][0][0] = 0;
for(reg int i = 1; i <= N; i ++)
for(reg int j = 0; j <= K; j ++)
for(reg int k = 0; k <= num; k ++)
for(reg int s = 0; s < (1<<num); s ++){
if(j >= 1) F[i][j][k][s] = std::min(F[i][j][k][s], F[i-1][j-1][k][s]);
if((s & (1<<h[i]-1)) && k == h[i]){
int &t = F[i][j][k][s];
for(reg int p = 0; p <= num; p ++){
t = std::min(t, F[i-1][j][p][s] + (p != k));
t = std::min(t, F[i-1][j][p][s ^ (1<<k-1)] + (p != k));
}
}
}
int Ans = N, U = (1<<num)-1;
for(reg int j = 0; j <= K; j ++)
for(reg int i = 0; i <= num; i ++)
for(reg int s = 0; s < (1<<num); s ++) Ans = std::min(Ans, F[N][j][i][s] + cnt[s ^ U]);
printf("Case %d: %d
", ++ Test_cnt, Ans);
}
return 0;
}