【GDKOI2015】星球杯

【GDKOI2015】星球杯

Description
Description

Input
第一行两个整数 N (2 <= N <= 200)和 K(1 <= K <= N/2),分别表示参赛人数和每轮预赛的晋级人数。
接下来 N 行, 第 i 行为第 i 个选手的情况, 每行三个整数, 分别为该选手参加第一轮预赛的得分 Xi,参加第二轮预赛的得分 Yi,以及该选手的所属国度 Zi( 1 表示阿斯嘉德, 0表示米德加尔特)。
注意: Xi 之间的值互不相同, Yi 之间的值互不相同。

Output
输出一行一个整数,为阿斯嘉德最高的得分总和。

Sample

Input1:
5 2
90 60 0
40 50 1
3 1 1
4 4 0
1 2 1
Output1:
54

Data Constraint
对于 30%数据, N≤20;
对于 100%数据, N≤200, Xi, Yi 的总和小于 2^31。


Analysis

非常直白地,可以想到限制一个组,剩下的就是DP问题了
强行给第一个组设定一个阈值,也就是第一个组的第K名,得分为x
按照另一个组的得分排序
f[i][j]表示到了前i个人,第二组分配了j个,的最大贡献
1. 第一轮分数低于x的1国选手对答案无贡献,所以我们先筛除这部分选手;
2. 剩下:1国选手 和 第一轮分数不低于x的0国选手;
递推式显然

  • 对于0国选手(第一轮得分必不小于x):
    • a. 分配到第1轮(j < k):F[i+1][j+1] = max(F[i+1][j+1], F[i][j]);
    • b.分配到第2轮:F[i+1][j] = max(F[i+1][j], F[i][j]);
  • 对于1国的选手:
    • a.第一轮分数小于x: 若i-j < k, F[i+1][j] =max(F[i+1][j], F[i][j] + b[i]);
    • b.第一轮分数大于等于x:
      • 分配第一轮(j < k):
        F[i+1][j+1]=max(F[i+1][j+1], F[i][j] + a[i]);
      • 分配第二轮:
        a) 当 i - j < k 时,F[i+1][j] = max(F[i+1][j], F[i][j] + b[i]);
        b)否则,F[i+1][j] = max(F[i+1][j], F[i][j]);

code

#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 210

using namespace std;

int n,ans,f[N][N],k,d[N];
struct data{int x,y,z;}a[N];
bool cmp(data a,data b){return a.y>b.y;}

int main(){
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++)scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].z),d[i]=a[i].x;
    sort(a+1,a+n+1,cmp);
    for(int o=1;o<=n;o++){
        memset(f,255,sizeof(f));f[0][0]=0;
        int c=0;
        for(int i=1;i<=n;i++)if(a[i].z || a[i].x>=d[o]){
            ++c;
            for(int j=0;j<c;j++)if(f[c-1][j]>=0)if(!a[i].z){
                if(j<k)f[c][j+1]=max(f[c][j+1],f[c-1][j]);
                f[c][j]=max(f[c][j],f[c-1][j]);
            }else{
                if(c-j-1<k)f[c][j]=max(f[c][j],f[c-1][j]+a[i].y);else f[c][j]=max(f[c][j],f[c-1][j]);
                if(a[i].x>=d[o]){
                    if(j<k)f[c][j+1]=max(f[c][j+1],f[c-1][j]+a[i].x);
                    else f[c][j+1]=max(f[c][j+1],f[c-1][j]);
                }
            }
        }
        int tmp=0;for(int i=0;i<=c;i++)if(f[c][i]>tmp)tmp=f[c][i];
        if(tmp>ans)ans=tmp;
    }printf("%d",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/white_elephant/article/details/80314999