炉石传说(NUPT-1969)

题目来源:acm.njupt.edu.cn                                                                                   

    炉石传说

炉石传说是暴雪公司推出的一款卡牌游戏,游戏中玩家可以通过召唤仆从和施放法术的方式两两对战。每一个仆从又两项数值:攻击力和生命值。比如火车王这张牌,数值为6-2表示攻击力为6,生命值为2。在游戏过程中,如果两个仆从进行一次战斗,那么战斗之后血量将被扣除对方攻击力大小的数值,而攻击力不会改变。一旦血量小于等于0,仆从就死亡而从战场上移除。现在你有n个仆从,对手有m个仆从,你可以在一个回合战斗中消灭对方所有仆从吗?(一回合中每个仆从最多攻击一次,对手不会发动攻击)

Iuput:

第一行:一个正整数T,表示T组数据

每组数据的第一行是两个整数n,m,接下来n+m行每行又两个整数a,b表示仆从的攻击力和血量

Output:

如果可以消灭对方所有仆从,输出YES

否则输出NO

Sample Input

2

1 2

2 3

1 1

3 1

2 2

2 3

1 1

3 2

3 1

Sample Output

NO

YES

思路:

1.要消灭对方全部仆从,最起码的条件是我方仆从的数量大于等于对方仆从数量(即n>=m)

2.满足条件1时,我方仆从的攻击力与对方仆从的生命值都按从大到小的顺序排列,然后依次比较。若我方仆从攻击力大于等于对方仆从生命值,则继续比较。否则从剩下的仆从中选一个合适的一起攻击。(需要将已经攻击过的仆从做标记)。

(选择合适的仆从时,应该是 当前仆从的攻击力+再选择的仆从的攻击力>=对方仆从生命值

如 攻击力为  4 3 3 1   生命值为 5 3 2,选攻击力为3的仆从时就不能得到正确结果。选择过程见代码)

自定义函数的实现:

bool Judge(int *a,int *b,int n,int m)
{
	bool *as=new bool[n];  //两个BOOL类型数组标记已经攻击过的仆从
	bool *bs=new bool[m];
	int i,j,k;
	if(n<m)
	{
		return false;
	}
	else
	{
		for(i=0;i<n;i++)
		{
			as[i]=false;
		}
		for(j=0;j<m;j++)
		{
			bs[j]=false;
		}
		PaiXu(a,n);                  //自定义的排序函数,将我方仆从的攻击力以及
		PaiXu(b,m);                  //对方仆从的生命值从大到小排序
		i=0;j=0;
		while(i<n&&j<m)
		{
			if(as[i]==true)
			{
				i++;
			}
			if(a[i]>=b[j])
			{
				as[i]=true;
				bs[j]=true;
				i++;
				j++;
			}
			else
			{
			for(k=i+1;k<n&&as[k]==false;k++)  //最关键的地方:当我方攻击力最大的仆从
			{                                 //小于对方生命值最大的仆从时,需要从剩
				if(a[i]+a[k]<b[j])        //下的仆从中选择一个攻击力合适一起攻
                                 {break;
				}
			}
				a[i]+=a[k-1];          //如果在上一个循环中没有满足                                                              
                                as[k-1]=true;          //条件a[i]+a[k]<b[j]的数据,则选择当前
                                n--;                   //攻击力最小的
                                if(n-i-1<m-j-1)
                               {
                                  return false;
                                }
                              }
                          }
                       }
                    return true;
}               

void PaiXu(int *a,int n)
{
    int i,j,x;
    for(i=1;i<n;i++)
    {
        j=i;
        x=a[j];
        while(a[j-1]<x&&j>0)
        {
            a[j]=a[j-1];
            j--;
        }
        a[j]=x;
    }
}



主函数的实现:

#include"iostream"
using namespace std;
bool Judge(int *a,int *b,int n,int m);
void PaiXu(int *a,int n);
int *a,*b;
int q;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,m,i,j;
		cin>>n>>m;
		a=new int[n];b=new int[m];
		for(i=0;i<n;i++)
		{
			cin>>a[i]>>q;            //我方仆从,只用记录攻击力
		}
		for(j=0;j<m;j++)
		{
			cin>>q>>b[j];             //对方仆从,只用记录生命值
		}
		if(Judge(a,b,n,m)==true)
		{
			cout<<"YES"<<endl;
		}
		else
		{
			cout<<"NO"<<endl;
		}
	}
	return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值