解题思路
开一个结构体存储学生的序号、a值和c值。对输入的数据,先按c值排序,c值相同情况下按序号排序。
定义dp数组,dpij表示排序后的前i个人里,选了j人的最小满意度。
初始化:
bash
memset(dp,0x3f,sizeof(dp));
for (int i = 0; i <= n; i++) dp[i][0] = 0;
- 如果j是奇数,一种情况是如果前一个人和他同一个团体,不选第i个人,可以使dpij=dpi-1j;还有一种考虑选第i个人,dpij=min(dpij,dpi-1j-1+si.a-xsi.idx)。(+si.a-xsi.idx,我们可以这样考虑:最终t出去的人是偶数,现在j是奇数,所以根据不满意的计算ai+aj+x*|i-j|,后面会有一个数和j配对,这里就把j对应的序号si.idx减去)。
- 如果j是偶数,一种情况是选第i个,且上一个人和第i个人同组,就可以得出dpij=min(dpij,dpi-1j-1+si.a+x*si.idx)。还有一种情况是不选第i个人,则dpij=min(dpij,dpi-1j)。
AC Code
cpp
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,m,k,x,dp[5005][5005];
struct stu{
int a,c,idx;
friend bool operator<(stu p,stu q){
if(p.c!=q.c) return p.c<q.c;
return p.idx<q.idx;
}
}s[5005];
int main(){
cin>>n>>m>>k>>x;
m=n-m;
if(m%2) m++;
for(int i=1;i<=n;i++){
s[i].idx=i;
cin>>s[i].a;
}
memset(dp,0x3f,sizeof(dp));
for (int i = 0; i <= n; i++) dp[i][0] = 0;
for(int i=1;i<=n;i++)
cin>>s[i].c;
sort(s+1,s+n+1);
for(int i=1;i<=n;i++){
for(int j=1;j<=min(i*1ll,m);j++){
if(j%2!=0){
if(s[i].c==s[i-1].c) dp[i][j]=dp[i-1][j];
dp[i][j]=min(dp[i][j],dp[i-1][j-1]+s[i].a-x*s[i].idx);
}
else{
dp[i][j]=dp[i-1][j];
if(s[i].c==s[i-1].c) dp[i][j]=min(dp[i][j],dp[i-1][j-1]+s[i].a+x*s[i].idx);
}
}
}
if(dp[n][m]<1e18) cout<<dp[n][m];
else cout<<"Impossible";
return 0;
}