『题解』A20909帮助
2025-06-07 20:47:47
发布于:湖南
28阅读
0回复
0点赞
:
拿出的书可以放在任意位置, 所以可以先放在一边, 到最后处理。
设 ,即表示处理到第 本书,拿出了 本书,书架上最后一本书高度为 ,书架上的书高度状态为 时的混乱值。
策略有两个:
-
将 拿出,。
-
不将 拿出, 。
再考虑统计答案, 。
其中 表示 二进制 的个数。
按以上方式更新状态时间复杂度 ,但若使用状态去更新状态, 时间复杂度 。
CODE:
#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\n\n", ++ Test_cnt, Ans);
}
return 0;
}
整活:万行代码皆可压缩
#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\n\n", ++ Test_cnt, Ans);}return 0;}
全部评论 1
禁止抄袭!
2024-08-20 来自 浙江
2
有帮助,赞一个