EPIC Institute of Technology Round Summer 2024 (Div. 1 + Div. 2) D.World is Mine
dp[i][j]
的定义是前
i
i
i 种物品中 Bob 取
j
j
j 种物品所需的步骤i - j
为Alice操作次数 dp[i-1][j-1]+w[i-1]
为Bob操作次数 Alice操作次数应比Bob多,所以会有此dp条件
void solve()
//code here
int n;
cin >> n;
vector<int>arr(n + 1);
for(int i = 0;i < n;++i){
int tmp;cin >> tmp;
++arr[tmp];
}
vector<int>w;
for(int i = 0;i <= n;++i)
if(arr[i])w.push_back(arr[i]);
n = w.size();
vector<vector<int>>dp(2,vector<int>(n + 1,INT_MAX)); //dp[i][j] 前i种物品中bob取j种物品所需的步骤
//取INT_MAX是为了后面取min时好区分
dp[0][0] = dp[1][0] = 0;
for(int i = 1;i <= n;++i){
int I = i % 2; //因为数组太大会MLE,我们要开滚动
int I_1 = I ^ 1;
for(int j = 1;j <= i;++j){
dp[I][j] = dp[I_1][j];
if(dp[I_1][j - 1] + w[i - 1] <= i - j) //i - j为Alice操作次数 dp[i-1][j-1]+w[i-1]为Bob操作次数 Alice操作次数应比Bob多
dp[I][j] = min(dp[I_1][j],dp[I_1][j - 1] + w[i - 1]); //取到j个时步数用的越少越好,为了使后面更好的能被选
}
}
for(int i = n;i >= 0;--i)
if(dp[n % 2][i] != INT_MAX){cout << n - i << endl;return;}
}