ZR19CSP-S模拟赛十联测
作者:互联网
Day 1
http://www.zhengruioi.com/contest/388
分组
这题最主要是要分析出来按照经验值排序的时候组长要在组员的后面
然后设计状态DP
设
f
i
,
a
,
b
表
示
排
序
后
的
前
i
个
,
目
前
已
经
有
a
个
组
只
有
组
员
没
有
组
长
,
b
个
组
已
经
配
好
了
的
最
小
代
价
\large f_{i,a,b}表示排序后的前i个,目前已经有a个组只有组员没有组长,b个组已经配好了的最小代价
fi,a,b表示排序后的前i个,目前已经有a个组只有组员没有组长,b个组已经配好了的最小代价
然后对于当前的人,考虑他是加入成为组长,加入一个只有组员的组,还是作为组员,单独开一个只有组员没有组长的组
按照这个DP就好了
具体看代码吧
code:
#include<bits/stdc++.h>
#define N 5005
using namespace std;
struct A{
long long w, s;
int p;
}a[1000005];
int cmp(A x, A y){
if(x.w != y.w) return x.w > y.w;
if((x.p == 1 || x.p == 3) && y.p == 2) return 1;
if((y.p == 1 || y.p == 3) && x.p == 2) return 0;
return 1;
}
int n, m;
long long f[N][N];
int main(){
scanf("%d%d", &n, &m);
if(m * 2 > n){ //必定不合法
printf("-1");
return 0;
}
for(int i = 1; i <= n; i ++) scanf("%lld%lld%d", &a[i].w, &a[i].s, &a[i].p);
sort(a + 1, a + 1 + n, cmp);
memset(f, 0x3f, sizeof f);
f[0][0] = 0;
for(int i = 1; i <= n; i ++){
for(int j = min(m, i); j >= 0; j --){
for(int k = j; k >= 0; k --){
if((a[i].p == 1 || a[i].p == 3) && j) f[j][k] = min(f[j][k], f[j-1][k] + a[i].s);
if((a[i].p == 2 || a[i].p == 3) && k) f[j][k] = min(f[j][k], f[j][k-1] + a[i].s);
}
}
}
if(f[m][m] > 1e18) f[m][m] = -1;
printf("%lld", f[m][m]);
return 0;
}
标签:return,&&,ZR19CSP,int,long,赛十,联测,组员,个组 来源: https://blog.csdn.net/qq_38944163/article/details/116270533