• 东大OJ-1544: GG的战争法则


    题目描述

    你在桥上看风景
    看风景的人在楼上看你
    明月装饰了你的窗子
    你装饰了我的梦
    这是GG在长坂坡发出的感叹。

    三年前GG莫名的穿越到了三国时期,在这三年里他看尽了各种杀戮,心里早已麻木。GG他渴望和

    平,他渴望每个人都能够和平相处,相近如宾,但是纵使他驰骋沙场多年,也无法改变三国鼎立的局面,
    也无法阻止各地杀戮的发生。他很心痛。直到有 一天,有一个人的到来解开了他多年的心结。他就是楼
    天城,人称楼教主。他的到了使GG更加坚定了他的初衷,并且经过楼教主的点拨,他茅塞顿开,开创了
    他自己的一套战争法则。 于是乎!GG不断的游说在各国之间,不断的向各国君主灌输和平战争的理念,
    经过多年的努力,GG终于成功的劝说了A国和B国的国王放弃杀戮,改为和平战争的形式来维护自己国家
    的主权和人民的安全。之后在每次的战争之中,A国和B国都沿用了GG的战争法则。
    GG的战争法则是这样的:
    首先A国的国王ZSGGB国的国王EAGLE,他们分别随机抽取了n张牌(n<=100,牌的种数只有
    三种,分别为KillPeachFlash,他们一开始都各自拥有一滴血,Kill牌可以让对方掉一滴血;Flash牌可
    以躲避对方的Kill,使自己不掉血;Peach牌可以为自己补一滴血.现在每次战争分为多个回合,每个回合
    双方都可以出任意一种牌,只能出一张,后手可以选择不出牌,但是先手必须出牌。先手为每个回合先出牌
    的国王,后手为每个回合后出牌的国王.A国和B国的国王轮流当先手,即第一回合ZSGG先出牌,第二回合
    EAGLE先出牌,第三回合ZSGG先出牌,第四回合EAGLE先出牌,以此类推。
    在每个回合中,GG是这样设定:
    1.对于先手来说,如果他有Kill,则他会优先出Kill.如果没有Kill,那么他只能出另外两种牌中的一种(
    设他拥有FlashPeach),但对对方无伤害.
    2.对于后手来说,他只能防御或者补血,而不能出Kill牌反击,因为GG不准.
    127.0.0.1
    3.如果先手没牌出,则该回合结束,继续下一回合.
    4.双方都没牌出时,战争结束,或者在战争途中,任意一方先死的,战争都会立即结束,而活着的一方将赢得战
    争胜利.
    5.如果战争结束后双方都还活着,则血量多的一方将赢得战争的胜利,血量相同的则双方打平,(sang)
    (xin)(bing)(kuang)。而作为胜利者,将会得到GG独家赞助的萌萌哒气球....
    6.在每场战役中如果ZSGG赢得胜利,则输出The X battle's winner is ZSGG.;如果EAGLE赢得胜
    利,则输出The X battle's winner is EAGLE.;否则双方打平,则输出The X battle's winner is Both.
    ( X表示第几场战役。) 具体的请看输出。


    输入

    输入T组数据,代指T场战役。(T<=200)每组数据第一行输入n。接下来输入(n + n)行。前n行指代A国的

    牌,后n行指代B国的牌。每一行代指牌的种类(Kill,Peach,Flash)

    输出

    对于每组数据,按题目要求输出。(请仔细看题目输出格式)


    样例输入

    3
    2
    Peach
    Peach
    Flash
    Peach
    2
    Kill
    Flash
    Flash
    Flash
    1
    Flash
    Peach

    样例输出

    The 1st battle's winner is ZSGG.
    The 2nd battle's winner is Both.
    The 3rd battle's winner is EAGLE.
    

    提示

    第1到23的序数词写法.(英语缩写) 1st,2nd,3rd,4th,5th,6th,7th,8th,9th,10th,11th,12th,

    13th,14th,15th,16th,17th,18th,19th,20th,21st,22nd,23rd.


    解析:首先,必须厘清这道题的逻辑:

    若我是先手,有杀只能出杀,这是规则里面明确规定了的;

    如果没有杀,那就尽量出桃,因为桃子只能补一滴血,这是早晚的事儿,早晚都是只能顶一滴血

    如果没有桃,那就坑了,你出闪相当于白白的流失一张牌,对你没有丝毫的好处.但是你必须出,因为规则说了,先手若有牌必须出牌.

    若你是后手,并且敌人出了杀.你就要尽量躲避这张杀:闪或者桃.尽量用闪,因为桃还有别的用处,而闪只有一种用途.

    若你没闪,那就出一张桃吧!若你没桃,你就掉血吧!

    -----------------------------------------

    |  先手    |   后手且先手出的是杀  |

    -----------------------------------------

    |   杀       |                      闪               |

    ----------------------------------------

    |   桃       |                      桃               |

    ----------------------------------------

    |   闪      |                     掉血           |

    ---------------------------------------

    根据上面这个规律已经可以写出一个模拟程序了,这道题复杂度O(200*100),简直小.用模拟完美解决,又快又对.

    虽然如此,一旦数据量大了,模拟法必定超时.很显然,这个游戏的对战过程十分机械,完全可以用计算的方法求出来.

    还有一些规律:桃和闪是防御牌,杀是攻击牌.

    所以任何一个对局都分为两个阶段:对杀阶段(你杀我我杀你,你闪我也闪);

    吊打阶段(我打你你打我).

    如果对杀阶段,你就跪了,那我就笑了.

    如果到了吊打阶段,计算出被吊打者最多能够承受多少张杀.


    你若是先手,你出桃,我指定不搭理你.留着就行了.

    你若是先手,你出闪,我指定也不搭理你.




     

    #include<stdio.h>
    struct Man
    {
    	int kill, peach, flash;
    	int num;
    	Man(int x)
    	{
    		kill = peach = flash = 0;
    		num = x;
    	}
    	void show(){
    		printf("num: %d kill:%d  peach:%d   flash:%d
    ", num, kill, peach, flash);
    	}
    };
    int ifKill(Man&a, int k){
    	if (k <= a.peach + a.flash)return -1;
    	else return a.peach + a.flash + 1;
    }
    void suffer(Man&a, int k){
    	if (k>a.flash){
    		k -= a.flash;
    		a.peach -= k;
    		a.flash = 0;
    	}
    	else{
    		a.flash -= k;
    	}
    }
    int go(Man&a, Man&b){
    	int akb = ifKill(b, a.kill);
    	int bka = ifKill(a, b.kill);
    	if (akb != -1){
    		if (akb <= bka)return 1;
    		else return 2;
    	}
    	if (a.kill<b.kill){
    		suffer(a, a.kill);
    		suffer(b, a.kill);
    		b.kill -= a.kill;
    		a.kill = 0;
    		int sum = a.flash + a.peach;
    		int x = sum >> 1;
    		int survive = x;
    		if (sum & 1){
    			if (a.flash>x){
    				survive += a.peach;
    				a.flash -= (x + 1 - a.peach);
    			}
    			else{
    				survive += x + 1;
    			}
    		}
    		else{
    			if (a.flash>x){
    				survive += a.peach;
    				a.flash -= (x - a.peach);
    			}
    			else{
    				survive += x;
    			}
    		}
    		if (survive<b.kill){
    			return 2;
    		}
    		else{
    			suffer(a, b.kill);
    		}
    	}
    	else if (a.kill>b.kill){
    		suffer(a, b.kill);
    		suffer(b, b.kill);
    		a.kill -= b.kill;
    		b.kill = 0;
    		int sum = b.peach + b.flash;
    		int x = sum >> 1;
    		int survive = x;
    		if (sum & 1){
    			survive++;
    			if (b.peach <= x){
    				survive += b.peach;
    				b.flash -= (x - b.peach);
    			}
    			else{
    				survive += x;
    			}
    		}
    		else{
    			if (b.peach <= x){
    				survive += b.peach;
    				b.flash -= (x - b.peach);
    			}
    			else{
    				survive += x;
    			}
    		}
    		if (survive<a.kill){
    			return 1;
    		}
    		else{
    			suffer(b, a.kill);
    		}
    	}
    	else{
    		suffer(a, b.kill);
    		suffer(b, a.kill);
    	}
    	if (a.peach>b.peach)return 1;
    	else if (a.peach<b.peach)return 2;
    	else return 0;
    }
    void input(Man&a, int size)
    {
    	char x[20];
    	for (int i = 0; i<size; i++)
    	{
    		scanf("%s", x);
    		if (x[0] == 'P')a.peach++;
    		else if (x[0] == 'K')a.kill++;
    		else a.flash++;
    	}
    }
    char who[][10] = { "Both", "ZSGG", "EAGLE" };
    void output(int t, int ans)
    {
    	printf("The %d", t);
    	if ((t / 10) % 10 != 1)
    	{
    		if (t % 10 == 1)printf("st");
    		else if (t % 10 == 2)printf("nd");
    		else if (t % 10 == 3)printf("rd");
    		else printf("th");
    	}
    	else printf("th");
    	printf(" battle's winner is %s.
    ", who[ans]);
    }
    int main()
    {
    	// freopen("C:\Users\weidiao\Documents\JavaProject\javaProject\实验室\in.txt","r",stdin);
    	int T;
    	scanf("%d", &T);
    	for (int t = 1; t <= T; t++)
    	{
    		int size;
    		scanf("%d", &size);
    		Man a(1), b(2);
    		input(a, size);
    		input(b, size);
    		int ans = go(a, b);
    		output(t, ans);
    	}
    	return 0;
    }
    
    /**************************************************************
    Problem: 1544
    User: 20124003
    Language: C++
    Result: 正确
    Time:3 ms
    Memory:800 kb
    ****************************************************************/


  • 相关阅读:
    简易仿ios菊花加载loading图
    android 仿微信表情雨下落!
    android view 转Bitmap 生成截图
    设计模式——享元模式
    虚拟内存技术原理解析
    读史——回望勾吴
    android日志搜集原理及方案比较
    java四种引用及在LeakCanery中应用
    读史——秦历史概况
    git使用总结
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/5013885.html
Copyright © 2020-2023  润新知