zoukankan      html  css  js  c++  java
  • Day4 T2 卡牌游戏

    题目

      小X为了展示自己高超的游戏技巧,在某一天兴致勃勃地找小Y玩起了一种卡牌游戏。每张卡牌有类型(攻击或防御)和力量值两个信息。小Y有n张卡牌,小X有m张卡牌。已知小X的卡牌全是攻击型的。
      游戏的每一轮都由小X 进行操作,首先从自己手上选择一张没有使用过的卡牌X。如果小Y手上没有卡牌,受到的伤害为X的力量值,否则小X要从小Y的手上选择一张卡牌Y。若Y是攻击型(当X的力量值不小于Y的力量值时才可选择),此轮结束后Y 消失,小Y受到的伤害为X的力量值与Y 的力量值的差;若Y是防御型(当X的力量值大于Y的力量值时才可选择),此轮结束后Y消失,小Y不受到伤害。
      小X可以随时结束自己的操作(卡牌不一定要用完)。希望聪明的你帮助他进行操作,使得小Y受到的总伤害最大。
      PS:原题:CF321B Ciel and Duel

    输入

    输入的第一行包含两个整数n和m。
    接下来n 行每行包含一个字符串和一个整数,分别表示小Y的一张卡牌的类型(“ATK”表示攻击型,“DEF”表示防御型)和力量值。
    接下来m 行每行包含一个整数,表示小X的一张卡牌的力量值。

    输出

    输出一行包含一个整数,表示小Y受到的最大总伤害。

    样例

    输入 输出
    2 3
    ATK 2000
    DEF 1700
    2500
    2500
    2500
    3000
    3 4
    ATK 10
    ATK 100
    ATK 1000
    1
    11
    101
    1001
    992

    数据规模

    各规模均有一半数据满足小Y 只有攻击型卡牌。
    对于30%的数据,1≤n,m≤6。
    对于60%的数据,1≤n,m≤(10^3)
    对于100%的数据,1≤n,m≤(10^5),力量值均为不超过(10^6)的非负整数。

    题解

    考虑两种策略:
    1.不动对方的防御牌,直接用我方最大的牌攻击对方最小的攻击牌,直到打不动为止。
    2.用大小最相近的牌将对方所有的牌消耗光,再用余下的牌造成满伤害。
    我们很难以决策这两种策略哪一种更优,怎么办办?
    ——很简单,两种策略都使用一遍,取答案更优的。

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ull;
    const int MAXN=100010;
    int n,m,cntatk,cntdef;
    int a[MAXN],atk[MAXN],def[MAXN];
    bool book[MAXN]={false};
    ull ans1=0,ans2=0;
    
    void solve1(){
    	for(int i=1,j=m;a[j]>atk[i] && j>0 && i<=cntatk;i++,j--) ans1+=a[j]-atk[i];
    }
    
    void solve2(){
    	for(int i=1,j=1;i<=cntdef;i++){
    		while((a[j]<=def[i] || book[j]) && j<=m) j++;
    		if(j==m+1){
    			ans2=0;//如果连对方的防御牌都打不完,这种策略的得分为0
    			return;
    		}
    		book[j]=true;
    	}
    	for(int i=1,j=1;i<=cntatk;i++){
    		while((a[j]<atk[i] || book[j]) && j<=m) j++;
    		if(j==m+1) return;//如果打不完对方攻击牌,直接退出 
    		ans2+=a[j]-atk[i];
    		book[j]=true;
    	}
    	for(int i=1;i<=m;i++){
    		if(!book[i]) ans2+=a[i];
    	}
    }
    
    int main(){
    	scanf("%d %d",&n,&m);
    	char ch[5];
    	int t;
    	for(int i=1;i<=n;++i){
    		scanf("%s %d",ch,&t);
    		if(ch[0]=='A') atk[++cntatk]=t;
    		else def[++cntdef]=t;
    	}
    	for(int i=1;i<=m;i++) scanf("%d",&a[i]);
    	sort(atk+1,atk+cntatk+1);
    	sort(def+1,def+cntdef+1);
    	sort(a+1,a+m+1);
    	solve1();
    	solve2();
    	printf("%lld",max(ans1,ans2));
    	return 0;
    }
    
  • 相关阅读:
    MSCRM 2011 自定义页面 CrmService 实现增,删,改,查需要注意的
    Microsoft Dynamics CRM 4.0,IFD验证下,自定义aspx页面,如何获取当前的用户ID ?
    CRM 4.0表单脚本开发一览
    MSCRM关于时区时间的操作
    常用JS操作方法
    详解 Visual C# 数据库编程
    Java 日志
    《信息检索导论》第二十章总结
    java文件添加包语句后的编译和运行问题
    查看端口占用情况:FPort和Moo0 ConnectionWatcher软件介绍
  • 原文地址:https://www.cnblogs.com/znk161223/p/11516672.html
Copyright © 2011-2022 走看看