题意:
给n个人,每个人有自己的意愿以及工作经验,表示能当组长,表示能当组员,表示既能当组长又能当组员,并且有雇佣他的花费,现在需要将这些人分成组,每组个人,,每个组有个组长和个组员,要求组长的工作经验不小于组员的工作经验,请问组成个队的最小花费,或者这是不可能的。
考虑DP,首先要满足组长经验不小于组员,我们可以将这些人重新编号,如果他想当组长就编号为,两个都可以就编号,否则编号,然后按照工作经验为第一关键字,编号为第二大关键字排序,设表示现在编好了个组,还剩下个组员可以选择。设当前人花费为,转移分三种情况考虑:
- 当前人编号为:
- 当前人编号为:
- 当前人编号为:综合上面两种情况转移。
#include <bits/stdc++.h>
#define int long long
#define regi register int
int n,k;
long long f[5010][5010];
struct people{
int exp;
int cost;
int wonder;
}p[1000001];
inline int read(){
int r=0,w=0,c;
for(;!isdigit(c=getchar());r=c);
for(w=c^48;isdigit(c=getchar());w=w*10+(c^48));
return r^45?w:-w;
}
bool cmp(people x,people y){
return x.exp==y.exp?x.wonder<y.wonder:x.exp<y.exp;
}
main(){
n=read(),k=read();
if(n<k*2){
puts("-1");
return 0;
}
for(regi i=1;i<=n;++i){
p[i]={read(),read(),read()};
if(p[i].wonder==1)
p[i].wonder=3;
else if(p[i].wonder==2)
p[i].wonder=1;
else if(p[i].wonder==3)
p[i].wonder=2;
}
std::sort(p+1,p+n+1,cmp);
for(regi i=0;i<=k+1;++i)
for(regi j=0;j<=k+1;++j)
f[i][j]=0x3f3f3f3f3f3f3f3fLL;
f[0][0]=0;
for(regi i=1;i<=n;++i)
for(regi j=k;j>=0;--j)
for(regi u=k;u>=0;--u){
if(p[i].wonder==3&&j<k&&u)
f[j+1][u-1]=std::min(f[j+1][u-1],f[j][u]+1LL*p[i].cost);
if(p[i].wonder==1&&u<k)
f[j][u+1]=std::min(f[j][u+1],f[j][u]+1LL*p[i].cost);
if(p[i].wonder==2){
if(j<k&&u)
f[j+1][u-1]=std::min(f[j+1][u-1],f[j][u]+1LL*p[i].cost);
if(u<k)
f[j][u+1]=std::min(f[j][u+1],f[j][u]+1LL*p[i].cost);
}
}
printf("%lld\n",f[k][0]==0x3f3f3f3f3f3f3f3fLL?-1LL:f[k][0]);
return 0;
}