问题描述
Rainbow 擅长玩战棋类游戏。著名的战棋游戏有很多,例如《曹操传》、《瓦岗 山异闻录》等。在本题中,我们考虑战棋游戏的一个简单版本,基于以下规则:
- 地图
地图是一个 N 行 M 列的矩阵,矩阵中的不同位置有不同的地形,例如平 原、树林、山地、河流、雪原等。在这里,我们给矩阵中的每个位置(i,j) (i,j) 规 定一个正整数G i,j Gi,j 这个整数会对在矩阵中的移动产生影响。
- 角色
每个角色均可被视作位于矩阵中某个位置上的人物。每个角色具有生命值 HP HP , 攻击力AT AT , 移动力MV MV 和攻击范围[AD 1 ,AD 2 ] [AD1,AD2] 。角色被分为两个阵营, 第 0 阵营被玩家控制,第 1 阵营被系统控制。 当两个不同阵营的角色 p p 和 q q 的曼哈顿距离处于 p p 的攻击范围内(包含端 点)时,p p 可以攻击 q q 。若 q q 被 p p 攻击,则 q q 的生命值被减去 p p 的攻击力。 当一个角色的生命值 ≤0 ≤0 时,它将立即被移除出地图,离开游戏。 每个角色均占领地图上的一个位置,并且可以在地图上移动,遵循以下规则:
- 占领
最初,每个角色在地图的不同位置生成。他们各自占领自己所在的位置。 当一个角色在移动时,其它角色均不能移动。 一个角色开始移动前失去对所在位置的占领权,停止移动时获得所在位置 的占领权。
- “移动”与“步”
一次移动由若干步组成。在每一步中,一个角色可以从当前位置走向四个 方向上相邻的位置,但不能走到被其它角色占领的位置上。
当一个角色从(i,j) (i,j) 走到 (x,y) (x,y) 时, 它的移动力会被扣除 G x,y Gx,y 。使得移动力变为负数的“步”是不合法的。在合法的一“步”完成后,若该角色正 处于与对方阵营某个角色相邻(四个方向)的位置上,则该角色的移动力 立即被减为 0,换句话说,他将不能再走另外一步。 当一次“移动”结束后,角色的移动力恢复为初始值。
能被一个角色通过若干合法“步”到达的位置集合称为该角色的移动范围。停留在原地也是合法的,故也被算入移动范围。
游戏的过程由若干轮组成,每轮玩家阵营先行动,系统阵营后行动。对于每个 阵营,该阵营的所有角色轮流行动。在每次行动中,一个角色先移动到移动范围 内的任意一个位置,然后可能会攻击对方阵营的一个角色(或什么也不做)。 当 一个阵营的所有角色均被移除出地图时,另外一个阵营获胜。 Rainbow 得到了一份游戏日志,请帮他复原这个游戏的过程。
输入格式
第一行 4 个整数 N,M,C,E(1≤N,M≤100,2≤C≤min(N×M,100),1≤E≤3000) N,M,C,E(1≤N,M≤100,2≤C≤min(N×M,100),1≤E≤3000) , 表示地图行数、列数、角色数、日志事件数。 接下来N N 行每行M M 个整数 G i,j (1≤G i,j ≤10 2 ) Gi,j(1≤Gi,j≤102) 。
接下来 C C 行每行 8 个整数 HP,AT,MV,AD 1 ,AD 2 ,ST x ,ST y ,GR(1≤HP,AT,MV≤10 3 , HP,AT,MV,AD1,AD2,STx,STy,GR(1≤HP,AT,MV≤103, 1≤AD 1 ≤AD 2 ≤20,1≤ST x ≤N,1≤ST y ≤M,0≤GR≤1) 1≤AD1≤AD2≤20,1≤STx≤N,1≤STy≤M,0≤GR≤1) , 表示角色的 5 个属性以及初始位置、所属阵营。
接下来 E E 行描述日志中的事件,每个事件都是以下格式之一: Round of GR – 阵营 GR GR 行动回合开始。 Action of character ID – 角色 ID ID 行动开始。 Move to (x,y) – 当前行动角色通过若干步移动到 (x,y) (x,y) 。 Attack ID – 当前行动角色攻击角色 ID ID 但是角色 ID ID 在攻击后未被移除。 Drive out ID – 当前行动角色攻击角色 ID ID 并造成 ID ID 被移出游戏。 在事件中, 1≤x≤N,1≤y≤M,1≤ID≤C,0≤GR≤1 1≤x≤N,1≤y≤M,1≤ID≤C,0≤GR≤1 。 行列标号从 1 开始,每个阵营初始至少拥有 1 个角色。
输出格式
对于每个Move to事件, 若无法到达,输出“INVALID”,否则输出当它进入终 点,准备结束“移动”前最多剩余多少移动力(移动力变化的优先顺序为:减去G→ G→ 若与对方阵营相邻扣为 0→ 0→ 输出→ → 恢复初始值)。 对于每个Attack or Drive out事件,若不能攻击或者攻击造成的是否移出地图的情况与输入不相符,输出“INVALID”,否则输出攻击后被攻击角色剩余 HP HP 。 不合法的事件在处理后续事件时应当被忽略。数据保证输入完成时游戏恰好结束,并且Round of and Action of类事件被正确记录,没有缺失或者矛盾。
样例输入
5 5 4 12
1 9 1 4 4
1 9 1 2 4
1 9 1 1 2
2 9 2 7 3
2 3 2 6 1
10 5 8 1 3 1 1 0
20 10 5 1 2 2 1 0
19 10 5 1 2 5 2 1
25 25 3 1 1 5 5 0
Round of 0
Action of character 2
Move to (5,1)
Attack 3
Action of character 1
Move to (3,1)
Round of 1
Action of character 3
Drive out 1
Round of 0
Action of character 2
Drive out 3
样例输出
0
9
6
INVALID
-1
数据规模与约定
对于 80% 80% 的数据,不存在不合法事件。
对于 100% 100% 的数据,参见输入输出格式中给定的范围与保证。
题解
暴力???(应该吧)
1 #include<iostream> 2 #include<queue> 3 #include<stack> 4 #include<cstdio> 5 #include<cstring> 6 #include<algorithm> 7 using namespace std; 8 const int Max=111; 9 int x0[4]={0,1,0,-1},y0[4]={1,0,-1,0}; 10 int map[Max][Max],G[Max][Max],DT[Max][Max],IN[Max][Max],n,m,c,e,gr,character; 11 char Event[30]; 12 queue <int> Qx,Qy; 13 struct Data{ 14 int HP,AT,MV,AD1,AD2,X,Y,GR; 15 }Character[Max]; 16 int Level(char Event[30]){ 17 if(Event[0]=='R'){ 18 return 1; 19 } 20 if(Event[0]=='A' && Event[1]=='c'){ 21 return 2; 22 } 23 if(Event[0]=='M'){ 24 return 3; 25 } 26 if(Event[0]=='D'){ 27 return 4; 28 } 29 return 5; 30 } 31 int CloseEnemy(int x,int y){ 32 return (map[x-1][y]==1-gr) || (map[x+1][y]==1-gr) || (map[x][y-1]==1-gr) || (map[x][y+1]==1-gr); 33 } 34 void Move(int Ex,int Ey){ 35 if(Character[character].HP<0){ 36 printf("INVALID\n"); 37 return; 38 } 39 for(int i=1;i<=n;i++){ 40 for(int j=1;j<=m;j++){ 41 DT[i][j]=1<<30; 42 IN[i][j]=0; 43 } 44 } 45 int Sx=Character[character].X,Sy=Character[character].Y; 46 for(Qx.push(Sx),Qy.push(Sy),DT[Sx][Sy]=0,IN[Sx][Sy]=0;!Qx.empty();Qx.pop(),Qy.pop()){ 47 int x=Qx.front(),y=Qy.front(); IN[x][y]=0; 48 for(int i=0;i<4;i++){ 49 int xx=x+x0[i],yy=y+y0[i]; 50 if(xx<1 || xx>n || yy<1 || yy>m || map[xx][yy]!=-1){ 51 continue; 52 } 53 if(CloseEnemy(xx,yy)){ 54 DT[xx][yy]=max(Character[character].MV,DT[x][y]+G[xx][yy]); 55 }else if(DT[x][y]+G[xx][yy]<DT[xx][yy]){ 56 DT[xx][yy]=DT[x][y]+G[xx][yy]; 57 if(IN[xx][yy] || DT[xx][yy]>=Character[character].MV){ 58 continue; 59 } 60 Qx.push(xx); Qy.push(yy); IN[xx][yy]=1; 61 } 62 } 63 } 64 if(DT[Ex][Ey]>Character[character].MV){ 65 printf("INVALID\n"); 66 }else{ 67 printf("%d\n",Character[character].MV-DT[Ex][Ey]); 68 map[Sx][Sy]=-1; 69 map[Ex][Ey]=gr; 70 Character[character].X=Ex; 71 Character[character].Y=Ey; 72 } 73 74 } 75 void Drive(int Enemy){ 76 if(Character[character].HP<0){ 77 printf("INVALID\n"); 78 return; 79 } 80 int dist=abs(Character[character].X-Character[Enemy].X)+abs(Character[character].Y-Character[Enemy].Y); 81 if(Character[Enemy].HP>0 && dist>=Character[character].AD1 && dist<=Character[character].AD2 && Character[character].AT>=Character[Enemy].HP){ 82 printf("%d\n",Character[Enemy].HP-=Character[character].AT); 83 map[Character[Enemy].X][Character[Enemy].Y]=-1; 84 }else{ 85 printf("INVALID\n"); 86 } 87 } 88 void Attack(int Enemy){ 89 if(Character[character].HP<0 || Character[Enemy].GR==gr){ 90 printf("INVALID\n"); 91 return ; 92 } 93 int dist=abs(Character[character].X-Character[Enemy].X)+abs(Character[character].Y-Character[Enemy].Y); 94 if(Character[Enemy].HP>0 && dist>=Character[character].AD1 && dist<=Character[character].AD2 && Character[character].AT<Character[Enemy].HP){ 95 printf("%d\n",Character[Enemy].HP-=Character[character].AT); 96 }else{ 97 printf("INVALID\n"); 98 } 99 return ; 100 } 101 int main(){ 102 scanf("%d%d%d%d",&n,&m,&c,&e); 103 for(int i=1;i<=n;i++){ 104 for(int j=1;j<=m;j++){ 105 scanf("%d",&G[i][j]); 106 } 107 } 108 memset(map,-1,sizeof(map)); 109 for(int i=1;i<=c;i++){ 110 scanf("%d%d%d%d%d%d%d%d\n",&Character[i].HP,&Character[i].AT,&Character[i].MV,&Character[i].AD1,&Character[i].AD2,&Character[i].X,&Character[i].Y,&Character[i].GR); 111 map[Character[i].X][Character[i].Y]=Character[i].GR; 112 } 113 for(int i=1;i<=e;i++){ 114 gets(Event); 115 int level=Level(Event); 116 if(level==1){ 117 gr=Event[9]-'0'; 118 } 119 if(level==2){ 120 character=0; 121 for(int j=20;Event[j]>='0' && Event[j]<='9';j++){ 122 character=character*10+Event[j]-'0'; 123 } 124 } 125 if(level==3){ 126 int j,Ey=0,Ex=0; 127 for(j=9;Event[j]>='0' && Event[j]<='9';j++){ 128 Ex=Ex*10+Event[j]-'0'; 129 } 130 for(j++;Event[j]>='0' && Event[j]<='9';j++){ 131 Ey=Ey*10+Event[j]-'0'; 132 } 133 Move(Ex,Ey); 134 } 135 if (level==4){ 136 int Enemy=0; 137 for(int j=10;Event[j]>='0' && Event[j]<='9';j++){ 138 Enemy=Enemy*10+Event[j]-'0'; 139 } 140 Drive(Enemy); 141 } 142 if(level==5){ 143 int Enemy=0; 144 for(int j=7;Event[j]>='0' && Event[j]<='9';j++){ 145 Enemy=Enemy*10+Event[j]-'0'; 146 } 147 Attack(Enemy); 148 } 149 } 150 return 0; 151 }