hiho #1571 : 小Hi与钢铁侠 【贪心】

题目大意

传送门

描述

小Hi在帮助钢铁侠开发新的盔甲。这套新盔甲一共包含M种武器插槽,其中第i种插槽有Ci个。每个插槽最多安装一个武器模块。

小Hi一共准备了N个武器模块,编号1~N。每个武器模块都有三个参数Vi, Pi和Ti。其中Vi描述了第i个模块的威力,Pi描述了该模块可以安装在哪种插槽中,Ti描述了该模块是否需要JARVIS的支持(1代表需要JARVIS支持,0代表不需要JARVIS支持)。

由于JARVIS的运算能力有限,它最多能同时支持K个武器模块。

现在小Hi想知道,如何装备武器模块才能使总威力最大,同时需要JARVIS支持的模块不超过K个。

输入
输入第一行包含一个整数T,代表测试数据的组数。

对于每组测试数据:

第一行包含三个整数N,M和K。

以下N行每行包含三个整数Vi, Pi和Ti。

最后一行包含M个整数,C1, C2, … CM。

对于30%的数据, T <= 20, N <= 100, M <= 10, K <= 100

对于另70%的数据, T <= 2, 1 <= N <= 105, 1 <= M <= 104, 0 <= K <= 105

对于100%的数据, 1 <= Vi <= 100, 1 <= Pi <= M, 0 <= Ti <= 1, 0 <= Ci <= 100

输出

输出最大的总威力。

思路

错误思路1

开始的时候我想了一个样例为:

1
3 2 1
100 1 1
99 1 0
40 2 1
1 1

即只有2种武器插槽,1个JARVIS支持,2种武器插槽分别最多安装[1 1]个武器模块。
3个武器分别为
100 1 1
99 1 0
40 2 1

这种情况的最优解应该是
第一种武器插槽安装 99 1 0
第二种武器插槽安装 40 2 1

这样直接的贪心(对武器的威力排序,从上往下依次扫一遍得到结果)是得不到正确结果的。

于是我就想贪心,用p_p[i][j]表示第i种武器插槽在插的武器总数小于Ci的基础上,分配给j个JARVIS支持的时候,威力的最大值。

然后在利用背包算得最后的结果。

可是背包的复杂度太高了,会超时。

正确思路

对每个武器插槽都计算一个不用JARVIS支持的时候威力的最大值。
然后对每个武器插槽都计算

  • 分配第一个JARVIS支持的收益值
  • 分配第二个JARVIS支持的收益值

比如第一个武器插槽中:若C[1] = 2,那么不用JARVIS支持的时候威力的最大值为98 + 97

100 1 1 
99 1 1 
98 1 0
97 1 0
40 1 0
  • 分配第1个JARVIS支持的收益为:100 - 97 = 3
  • 分配第2个JARVIS支持的收益为:99 - 98 = 1

之后对所有的收益排序,取前K个即可。

代码


#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

#define maxn2 10005

#define min(a,b) (a>b)? b:a
#define max(a,b) (a>b)? a:b

int TT;
int N,M,K;//N个武器 M个插槽 K个jarvis支持


int vectorSize(vector<int> V,int n){
    int sum = 0;
    for(int i = 0;i<n;i++){
        sum+=V[i];
    }
    return sum;
}

bool cmp(int x1, int x2){
    return x1>x2;
}

struct Node{
    vector<int> T0;//储存
    vector<int> T1;//储存
};
vector<Node> P;

int C[maxn2];
int pre_cnt[maxn2];//第i个武器插槽不使用JARVIS支持的威力

int main (){
    scanf("%d",&TT);
    while(TT--){

        scanf("%d%d%d",&N,&M,&K);//N个武器 M个武器插槽 K个jarvis支持

        P.resize(M+1);//

        for(int i = 0;i<=M;i++) P.clear();

        for(int i = 0;i<N;i++)
        {
            int temp_vv,temp_pp,temp_tt;
            scanf("%d%d%d",&temp_vv,&temp_pp,&temp_tt);
            if(temp_tt == 0) P[temp_pp].T0.push_back(temp_vv);//最好是把T0补0至Ci一样多 这样少了很多处理的判断
            if(temp_tt == 1) P[temp_pp].T1.push_back(temp_vv);

        }

        for(int i = 1; i <= M; i++){
            scanf("%d",&C[i]);
        }

        //若T0<Ci
        //最好是把T0补0至Ci一样多 这样少了很多处理的判断
        //判断有:直接加上T1的第一个字母或者是替换。
        for(int i = 0;i <= M; i++){
            int T0_size = P[i].T0.size();
            for(int j = 0; j<C[i]-T0_size; j++) P[i].T0.push_back(0);
        }


        for(int i = 1; i<=M;i++){
            sort(P[i].T0.begin(),P[i].T0.end(),cmp);
            sort(P[i].T1.begin(),P[i].T1.end(),cmp);

//            for(int j = 0;j<P[i].T0.size();j++){
//                printf("%d:[%d 0]\n",i,P[i].T0[j]);
//            }
//            for(int j = 0;j<P[i].T1.size();j++){
//                printf("%d:[%d 1]\n",i,P[i].T1[j]);
//            }
        }

        vector<int> Profit;
        Profit.clear();


        for(int i = 1; i<=M;i++){//第i个武器插槽
            int size_0 = P[i].T0.size();//不需要JARVIS支持的武器个数
            int size_1 = P[i].T1.size();//需要JARVIS支持支持的武器的个数

            pre_cnt[i] = vectorSize(P[i].T0,C[i]);;//第i个武器插槽不使用JARVIS支持的总威力

            //开始替换
            for(int j = 0;j<size_1;j++){
                if((C[i]-j-1 >= 0)&&P[i].T1[j] - P[i].T0[C[i]-j-1] > 0) Profit.push_back(P[i].T1[j] - P[i].T0[C[i]-j-1]);
            }
        }

        int Profit_sum = 0;

        //取前K个正的Profit作为利息的总值。
        //for(int i = 0;i<Profit.size();i++) printf("%d \n",Profit[i]);

        sort(Profit.begin(),Profit.end(),cmp);

        K = min(Profit.size(),K);

        for(int i = 0; i < K; i++) Profit_sum+=Profit[i];

        for(int i = 1; i <= M; i++) Profit_sum+=pre_cnt[i];

        printf("%d\n",Profit_sum);
    }

}
/*
1
5 2 1
100 1 1
99 1 1
98 1 0
97 1 0
40 2 1
3 1
*/

Hit

这个在T0的后面补0的操作很有灵性。

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、下4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、下4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值