【HDU1107】【模拟】武林 三个门派来回走定制方向单挑架

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<iostream>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=1010,M=0,Z=1e9+7,ms63=1061109567;
int casenum,casei;
int n,m;
struct A
{
	int typ;
	double atk;
	int y,x,hp;
	int d;
}a[N];
int b[14][14][3];
int num[3],hp[3];
int main()
{
	scanf("%d",&casenum);
	for(casei=1;casei<=casenum;casei++)
	{
		scanf("%d",&m);n=0;
		char ch;int atk1,atk2;
		while(scanf(" %c",&ch),ch!='0')
		{
			++n;scanf("%d%d%d%d%d",&a[n].y,&a[n].x,&atk1,&atk2,&a[n].hp);
			a[n].d=1;
			if(ch=='S')
			{
				a[n].typ=0;
				a[n].atk=0.005*atk1+0.005*atk2;
			}
			else if(ch=='W')
			{
				a[n].typ=1;
				a[n].atk=0.008*atk1+0.002*atk2;
			}
			else 
			{
				a[n].typ=2;
				a[n].atk=0.002*atk1+0.008*atk2;
			}
		}
		for(int i=1;i<=m;i++)
		{
			MS(b,0);
			for(int j=1;j<=n;j++)if(a[j].hp>0)
			{
                if(b[a[j].y][a[j].x][0]==0)b[a[j].y][a[j].x][0]=j;
                else if(b[a[j].y][a[j].x][1]==0)b[a[j].y][a[j].x][1]=j;
                else b[a[j].y][a[j].x][2]=j;
                if(a[j].typ==0)
                {
                    if(a[j].y==1)a[j].d=1;
                    else if(a[j].y==12)a[j].d=-1;
                    a[j].y+=a[j].d;
                }
                else if(a[j].typ==1)
                {
                    if(a[j].x==1)a[j].d=1;
                    else if(a[j].x==12)a[j].d=-1;
                    a[j].x+=a[j].d;
                }
                else
                {
					if(a[j].y==12&&a[j].x==1||a[j].y==1&&a[j].x==12)a[j].d=0;
                    else if(a[j].y==1||a[j].x==1)a[j].d=1;
                    else if(a[j].y==12||a[j].x==12)a[j].d=-1;
                    a[j].y+=a[j].d;
                    a[j].x+=a[j].d;
                }
			}
			for(int j=1;j<=12;j++)
			{
				for(int k=1;k<=12;k++)
				{
					if(b[j][k][2]==0&&b[j][k][1]!=0)
					{
						int p1=b[j][k][0];
						int p2=b[j][k][1];
						if(a[p1].typ!=a[p2].typ)
						{
							//一定要先算完攻击力后再把影响生效
							int atk1=a[p1].atk*(a[p1].hp+10);
							int atk2=a[p2].atk*(a[p2].hp+10);
							a[p1].hp-=atk2;
							a[p2].hp-=atk1;
						}
					}
				}
			}
		}
		MS(num,0);
		MS(hp,0);
		for(int j=1;j<=n;j++)if(a[j].hp>0)
		{
			++num[a[j].typ];
			hp[a[j].typ]+=a[j].hp;
		}
		for(int i=0;i<3;i++)printf("%d %d\n",num[i],hp[i]);
		puts("***");
	}
	return 0;
}
/*
【trick&&吐槽】
1,是先战斗再移动,顺序不要错
2,移动是有方向性的,要好好判定。

【题意】
给你一个12*12的棋盘
有n(1000)个人在棋盘中无限地走来走去。
人有三种——
1,S少林派,每次竖着走,走到头会再返回……
2,W武当派,每次横着走,走到头会再返回……
3,E峨眉派,每次斜着走,走到头会再返回……
告诉你每个人的——
派别,行号,列号,魔法攻击力,物理攻击力,初始生命值
少林派攻击力 = (0.5 * 内力 + 0.5 * 武艺) * (战前生命力 + 10) / 100
武当派攻击力 = (0.8 * 内力 + 0.2 * 武艺) * (战前生命力 + 10) / 100
峨嵋派攻击力 = (0.2 * 内力 + 0.8 * 武艺) * (战前生命力 + 10) / 100
然后我们要操作m步,
首先,如果一个位置恰有2个人,且这2个人属于不同的派别,那么这2个人会打一架。
然后,每个活着的人前进一步。
问你,经过这3步之后,每个派别剩下的人数和生命值之和。

【类型】
模拟

【分析】
模拟要学会简化问题,要学会归类

*/


你可能感兴趣的:(模拟,ACM,ICPC,codeforces)