題意:
給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;
}