ZOJ 3474 Taekwondo
Author: HUANG, Qiao
Contest: ZOJ Monthly, February 2011
H
算法核心:贪心
大意:
已知:
1.Alice 有n个敌人,现有的能量值为S
2.每个敌人的基本信息:p1,p2,p3,r.
其中p1为消耗敌人3个积分所需要的能量
p2为消耗敌人2个积分需要的能量
p3为消耗敌人1个积分所需能量,
r为消灭该敌人后所能获得的能量值
3.消灭一个敌人至少需要消耗它的积分7个
问Alice能否完全消灭这n个敌人,若能,求出Alice所能剩余的最大能量
分析:
1.对于每个敌人,计算出消灭它所需要的最小能量(只有三个状态,枚举p1,p2,p3的组合,使其积分和>=7,即可算出最小
消耗)
2.将敌人分为两组,第一组存放消耗值<得到值,第二组存放消耗值>=得到值的敌人
3.对于第一组,按能量的消耗值从小到大杀(易证)
4.对于第二组,按能量的得到值从大到小杀(将3的情形逆过来思考,即得)
#include<stdio.h> #include<algorithm> using namespace std; #include<string.h> const int N = 23; struct node { int cost;//需要消耗的能量 int get;//可以得到的能量 }; node stronger[N];//变强数 node weaker[N];//变弱 int snum; int wnum; //对获得值>付出值的人进行排序 inline bool cmps(node A,node B) { return A.cost<=B.cost;//按消费从小到大,即先杀小兵 } //对付出值>获得值的对手按返回值从大到小排 inline bool cmpw(node A,node B) { return (A.get>=B.get); } int getCost(int p1,int p2,int p3)//当获取3,2,1积分分别耗能p1时,计算获取>=7积分的最小耗能数 { int i,j,k; int cost = 3*p1; for(i=0;i<=3;i++) for(j=0;j<=4;j++) { k=i*3+j*2; int ccost = p1*i+p2*j; if(k<7) ccost=ccost+(7-k)*p3; if(ccost<cost)cost=ccost; } return cost; } int main() { int T; while(scanf("%d",&T)!=EOF) { while(T--) { int m,S; scanf("%d%d",&m,&S); wnum=0; snum=0; while(m--) { int p1,p2,p3,r; scanf("%d%d%d%d",&p1,&p2,&p3,&r); int cost = getCost(p1,p2,p3); if(r>cost) { stronger[snum].cost=cost; stronger[snum].get=r; snum++; } else { weaker[wnum].cost=cost; weaker[wnum].get=r; wnum++; } } sort(stronger,stronger+snum,cmps); sort(weaker,weaker+wnum,cmpw); int i; for(i=0;i<snum;i++) { //printf("%d %d\n",stronger[i].cost,stronger[i].get); if(S<=stronger[i].cost)break; S=S+stronger[i].get-stronger[i].cost; } if(i<snum) { printf("no\n"); continue; } // printf("OK\n"); for(i=0;i<wnum;i++) { if(S<=weaker[i].cost)break; //printf("%d %d\n",weaker[i].cost,weaker[i].get); S=S+weaker[i].get-weaker[i].cost; } if(i<wnum) { printf("no\n"); continue; } printf("%d\n",S); } } return 0; }