ZOJ 3474 Taekwondo【贪心】


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;

}

你可能感兴趣的:(ZOJ)