我的思路是 f[i][j] 表示考虑前 i 个人, 最后一队为第 j 队时最少的出列人数
f[i][j] = min{f[i-c][k]} + c-(s[i][j]-s[i-c][j])
其中, s[i][j] 表示前 i 个人中, 属于第 j 队的人数. c=s[n][j]
答案为 min{f[n][j]}
60 分. 说明有小 BUG 或者哪些地方没考虑到. 但我百思不得其解, 所以恳求路过大佬施与帮助.
#include <bits/stdc++.h>
#define REP(i, a, b) for(register int i = (a); i <=(b); ++i)
using namespace std;
ll read(){
ll x=0; int f=0, c=getchar();
for(; c<'0' || '9'<c; c=getchar()) f |= c=='-';
for(; '0'<=c&&c<='9'; c=getchar()) x = (x<<1)+(x<<3)+int(c^'0');
return f ?-x :x;
}
const int N = 1e5+9, M = 21;
const int INF = 0x3f3f3f3f;
int n, m;
int a[N], s[N][M], f[N][M], g[N];
int solve(){
REP(i, 1, n){
g[i] = INF;
REP(j, 1, m){
f[i][j] = INF;
int c = s[n][j];
if(i<c) continue;
f[i][j] = g[i-c] + c-(s[i][j]-s[i-c][j]);
g[i] = min(g[i], f[i][j]);
}
}
int ans = INF;
REP(i, 1, m) ans = min(ans, f[n][i]);
return ans;
}
int main(){
n = read(), m = read();
REP(i, 1, n){
a[i] = read();
REP(j, 1, m){
s[i][j] = s[i-1][j];
}
s[i][a[i]]++;
}
printf("%d\n", solve());
return 0;
}