10.09T3 大模拟

Rainbow擅长玩战棋类游戏。著名的战棋游戏有很多,例如《曹操传》、《瓦岗山异闻录》等。在本题中,我们考虑战棋游戏的一个简单版本,基于以下规则:
地图
地图是一个N行M列的矩阵,矩阵中的不同位置有不同的地形,例如平原、树林、山地、河流、雪原等。在这里,我们给矩阵中的每个位置规定一个正整数,这个整数会对在矩阵中的移动产生影响。
角色
每个角色均可被视作位于矩阵中某个位置上的人物。每个角色具有生命值HP, 攻击力AT, 移动力MV和攻击范围[AD1 AD2]。角色被分为两个阵营,第0阵营被玩家控制,第1阵营被系统控制。
当两个不同阵营的角色p和q的曼哈顿距离处于p的攻击范围内(包含端点)时,p可以攻击q。若q被p攻击,则q的生命值被减去p的攻击力。当一个角色的生命值<=0时,它将立即被移除出地图,离开游戏。
每个角色均占领地图上的一个位置,并且可以在地图上移动,遵循以下规则:
占领
最初,每个角色在地图的不同位置生成。他们各自占领自己所在的位置。当一个角色在移动时,其它角色均不能移动。 
一个角色开始移动前失去对所在位置的占领权,停止移动时获得所在位置的占领权。
“移动”与“步”
一次移动由若干步组成。在每一步中,一个角色可以从当前位置走向四个方向上相邻的位置,但不能走到被其它角色占领的位置上。
当一个角色从i,j 走到x,y 时, 它的移动力会被扣除Gx,y。使得移动力变为负数的“步”是不合法的。在合法的一“步”完成后,若该角色正处于与对方阵营某个角色相邻(四个方向)的位置上,则该角色的移动力立即被减为0,换句话说,他将不能再走另外一步。
当一次“移动”结束后,角色的移动力恢复为初始值。
能被一个角色通过若干合法“步”到达的位置集合称为该角色的移动范围。停留在原地也是合法的,故也被算入移动范围。
游戏的过程由若干轮组成,每轮玩家阵营先行动,系统阵营后行动。对于每个阵营,该阵营的所有角色轮流行动。在每次行动中,一个角色先移动到移动范围内的任意一个位置,然后可能会攻击对方阵营的一个角色(或什么也不做)。 当一个阵营的所有角色均被移除出地图时,另外一个阵营获胜。
Rainbow得到了一份游戏日志,请帮他复原这个游戏的过程。

Input

第一行 4 个整数 N,M,C,E(1≤N,M≤100,2≤C≤min(N×M,100),1≤E≤3000) 表示地图行数、列数、角色数、日志事件数。 接下来N行每行M个整数Gi,j(1≤Gi,j≤10^2) 。
接下来 C 行每行 8 个整数 HP,AT,MV,AD 1 ,AD 2 ,ST x ,ST y ,GR(1≤HP,AT,MV≤10^3, 1≤AD1≤AD2≤20,1≤STx≤N,1≤STy≤M,0≤GR≤1) , 表示角色的 5 个属性以及初始位置、所属阵营。 
接下来 E 行描述日志中的事件,每个事件都是以下格式之一: 
Round of GR – 阵营 GR 行动回合开始。 
Action of character ID – 角色ID 行动开始。 
Move to (x,y) – 当前行动角色通过若干步移动到 (x,y) 。 
Attack ID – 当前行动角色攻击角色ID 但是角色 ID在攻击后未被移除。 
Drive out ID – 当前行动角色攻击角色ID并造成ID 被移出游戏。
在事件中,1≤x≤N,1≤y≤M,1≤ID≤C,0≤GR≤1 。 行列标号从1开始,每个阵营初始至少拥有1个角色。

Output

对于每个Move to事件, 若无法到达,输出“INVALID”,否则输出当它进入终点,准备结束“移动”前最多剩余多少移动力(移动力变化的优先顺序为:减去G→ G→ 若与对方阵营相邻扣为 0→ 0→ 输出→ → 恢复初始值)。 
对于每个Attack or Drive out事件,若不能攻击或者攻击造成的是否移出地图的情况与输入不相符,输出“INVALID”,否则输出攻击后被攻击角色剩余 HP HP 。 
不合法的事件在处理后续事件时应当被忽略。数据保证输入完成时游戏恰好结束,并且Round of and Action of类事件被正确记录,没有缺失或者矛盾。

样例输入1

样例输出1

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

Hint

【数据规模与约定】
对于80%的数据,不存在不合法事件。
对于100%的数据,参见输入输出格式中给定的范围与保证。
 
 
 
 
 
 
 

【分析】

本题考察基本功,并没有太多的算法上的要求。

只需要认真阅读题意,谨慎地按照题目所要求的编写代码。

有几个需要注意的地方:

1·不能攻击队友。

2·可以走到原地。

3·移动中碰到队友是不会把移动力变成0的。

4·注意死亡的人要移除游戏,死亡后再操作是非法的。

5·本题的输入有点奇怪。有时会多几个空格。

 

code:

不存在的,我写不出来的

我的30分代码。。。。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #define N 200 
  6 using namespace std;
  7 long long dx[4]={0,0,1,-1};
  8 long long dy[4]={1,-1,0,0};
  9 long long group[N],stx[N],sty[N],n,m,C,E,survive[N];
 10 long long check_group(long long x,long long y,long long GROUP){//检查当前步是不是走到了对方的旁边 
 11     for(long long i=1;i<=C;i++){
 12         if(group[i]==GROUP)continue;//自己的人不需要有这些限定 
 13         if(survive[i]==0)continue;//死了 
 14         if(stx[i]==x&&sty[i]==y+1)return 1;//下面是检查相邻的部分 
 15         if(stx[i]==x&&sty[i]==y-1)return 1;
 16         if(stx[i]==x+1&&sty[i]==y)return 1;
 17         if(stx[i]==x-1&&sty[i]==y)return 1;
 18     }
 19     return 0;
 20 }
 21 long long max0=0,G[N][N],dis[N][N];
 22 void check_move(long long now_x,long long now_y,long long final_x,long long final_y,long long rest_MV,long long GROUP){
 23     if(dis[now_x][now_y]!=-1&&dis[now_x][now_y]>=rest_MV)return;
 24 //    cout<<"nowx->"<<now_x<<"  nowy->"<<now_y<<"  finalx->"<<final_x<<"  finaly->"<<final_y<<"  ->rest"<<rest_MV<<'\n';
 25     if(now_x==final_x&&now_y==final_y){
 26         if(dis[now_x][now_y]!=-1&&dis[now_x][now_y]>=rest_MV)return;
 27         dis[now_x][now_y]=rest_MV;
 28         max0=max(max0,rest_MV);//更新最大值 
 29         return;
 30     }
 31     dis[now_x][now_y]=rest_MV;
 32     if(rest_MV<=max0)return;
 33     if(rest_MV<=0)return ;//如果没能到达终点并且没有步数可以走了就直接不行 
 34     for(long long i=0;i<4;i++){
 35         long long tx=now_x+dx[i],ty=now_y+dy[i];
 36         if(check_group(tx,ty,GROUP)){//如果下一步是对方的旁边就直接削减成0 
 37             if(rest_MV-G[tx][ty]<0)continue;
 38             check_move(tx,ty,final_x,final_y,0,GROUP);
 39             continue;
 40         }
 41         if(tx>n||tx<1||ty<1||ty>m)continue;
 42         check_move(tx,ty,final_x,final_y,rest_MV-G[tx][ty],GROUP);
 43     }
 44 } 
 45 long long ad1[N],ad2[N],hp[N],at[N],mv[N],nowpeople,nowx,nowy,nowgroup;
 46 int main() {
 47     ios::sync_with_stdio(false);
 48     cin>>n>>m>>C>>E;
 49     for(long long i=1; i<=n; i++)
 50         for(long long j=1; j<=m; j++)
 51             cin>>G[i][j];
 52     for(long long i=1; i<=C; i++) {
 53         cin>>hp[i]>>at[i]>>mv[i]>>ad1[i]>>ad2[i]>>stx[i]>>sty[i]>>group[i];
 54         survive[i]=1;//这个人还活着,初始化
 55     }
 56     string k;
 57     while(E--) {
 58         cin>>k;
 59         string zyh;
 60         if(k=="Attack") { //打人但是没有打死的情况
 61             long long ID;
 62             cin>>ID;
 63             if(survive[ID]==0) {
 64                 cout<<"INVALID"<<'\n';//如果这个人已经死亡了,那么显然是不合法的
 65                 continue;
 66             }
 67             if(group[ID]==group[nowpeople]) { //如果是自己人当然就不合法
 68                 cout<<"INVALID"<<'\n';
 69                 continue;
 70             }
 71             long long distance=abs(stx[ID]-nowx)+abs(sty[ID]-nowy);
 72             if(distance>ad2[nowpeople]||distance<ad1[nowpeople]) { //如果打不到这个人就代表是不合法的
 73                 cout<<"INVALID"<<'\n';
 74                 continue;
 75             }
 76             if(hp[ID]-at[nowpeople]<=0) { //如果被打死了,在该状态下是不合法的
 77                 cout<<"INVALID"<<'\n';
 78                 continue;
 79             }
 80             hp[ID]-=at[nowpeople];//否则就减去这个人的值
 81             cout<<hp[ID]<<'\n';
 82         } else if(k=="Action") { //代表现在行动的人 ,因为题目描述没有矛盾,所以不做太多判断
 83             cin>>zyh;
 84             cin>>zyh;
 85             long long ID;
 86             cin>>ID;
 87             nowpeople=ID;
 88             nowx=stx[ID];
 89             nowy=sty[ID];
 90         } else if(k=="Round") { //代表该轮中行动的团队 ,题目描述没有矛盾,所以不做判断
 91             cin>>zyh;
 92             long long GR;
 93             cin>>GR;
 94             nowgroup=GR;
 95         } else if(k=="Move") {
 96             long long X=0,Y=0;
 97             cin>>zyh;
 98             cin>>k;
 99             long long flag=0;
100             for(long long i=0; i<k.size(); i++) {
101                 if(!isdigit(k[i])&&!flag)continue;
102                 if(isdigit(k[i])&&(flag==1||flag==0)) {
103                     flag=1;
104                     X=(X<<3)+(X<<1)+k[i]-'0';
105                     continue;
106                 }
107                 if(flag==1&&!isdigit(k[i])) {
108                     flag=2;
109                     continue;
110                 }
111                 if(isdigit(k[i])&&flag==2) {
112                     Y=(Y<<3)+(Y<<1)+k[i]-'0';
113                     continue;
114                 }
115             }
116             //cout<<X<<" "<<Y<<endl;/////////////
117             for(long long i=1; i<=C; i++) {
118                 if(X==stx[i]&&Y==sty[i]&&group[i]!=group[nowpeople]&&survive[i]) { //如果走到了对方的地方显然是不合法的
119                     cout<<"INVALID"<<'\n';
120                 }
121             }
122             max0=-1;
123             memset(dis,-1,sizeof dis);
124             check_move(nowx,nowy,X,Y,mv[nowpeople],group[nowpeople]);
125             if(dis[X][Y]==-1){
126                 cout<<"INVALID"<<'\n';
127                 continue;
128             }
129             cout<<dis[X][Y]<<'\n';
130             nowx=X,nowy=Y;
131             stx[nowpeople]=X,sty[nowpeople]=Y;
132         } else if(k=="Drive") {
133             cin>>zyh;
134             long long ID;
135             cin>>ID;
136             if(survive[ID]==0) {//这个人已经死亡了,显然是不合法的状态
137                 cout<<"INVALID"<<'\n';
138                 continue;
139             }
140             if(group[ID]==group[nowpeople]) { //如果是自己人当然就不合法
141                 cout<<"INVALID"<<'\n';
142                 continue;
143             }
144             long long distance=abs(stx[ID]-nowx)+abs(sty[ID]-nowy);
145             if(distance>ad2[nowpeople]||distance<ad1[nowpeople]) { //如果打不到这个人就代表是不合法的
146                 cout<<"INVALID"<<'\n';
147                 continue;
148             }
149             if(hp[ID]-at[nowpeople]>0) { //如果没有被打死,在该状态下是不合法的
150                 cout<<"INVALID"<<'\n';
151                 continue;
152             }
153             hp[ID]-=at[nowpeople];//否则就减去这个人的值
154             survive[ID]=0;//打标记代表这个人已经死亡了
155             stx[ID]=-9999;//坐标肯定要作废
156             sty[ID]=-9999;
157             cout<<hp[ID]<<'\n';
158         }
159     }
160     return 0;
161 }

正解AC的代码:

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cmath>
  5 using namespace std;
  6 int n,m,C,E,Rnd,id,G[105][105];
  7 int belong[105][105];
  8 int dis[105][105];
  9 struct Character{
 10     int HP,AT,MV,AD1,AD2;
 11     int x,y,GR;
 12     bool DIE;
 13 }p[105];
 14 int getint(){
 15     char c=getchar();int sum=0;
 16     while(!isdigit(c))c=getchar();
 17     while(isdigit(c)){sum=sum*10+c-48;c=getchar();}
 18     return sum;
 19 }
 20 int fx[]={1,-1,0,0};
 21 int fy[]={0,0,1,-1};
 22 void dfs(int x,int y,int mv,bool flag){
 23     if(mv<0)return;
 24     if(flag){
 25         if(belong[x-1][y]&&belong[x-1][y]!=Rnd+1)mv=0;
 26         if(belong[x+1][y]&&belong[x+1][y]!=Rnd+1)mv=0;
 27         if(belong[x][y-1]&&belong[x][y-1]!=Rnd+1)mv=0;
 28         if(belong[x][y+1]&&belong[x][y+1]!=Rnd+1)mv=0;
 29     }
 30     if(dis[x][y]>=mv)return;
 31     dis[x][y]=max(dis[x][y],mv);
 32     int xx,yy;
 33     for(int i=0;i<4;++i){
 34         xx=x+fx[i];yy=y+fy[i];
 35         if(xx>n||xx<1||yy>m||yy<1)continue;
 36         if(belong[xx][yy])continue;
 37         dfs(xx,yy,mv-G[xx][yy],true);
 38     }
 39 }
 40 void Move(int k){
 41     int x=getint(),y=getint();
 42     if(x==p[k].x&&y==p[k].y){
 43         cout<<p[k].MV<<"\n";
 44         return;
 45     }
 46     if(x>n||x<1||y>m||y<1){
 47         printf("INVALID\n");
 48         return;
 49     }
 50     memset(dis,-1,sizeof(dis));
 51     dfs(p[k].x,p[k].y,p[k].MV,false);
 52     if(dis[x][y]<0){
 53         printf("INVALID\n");
 54         return;
 55     }
 56     belong[p[k].x][p[k].y]=0;
 57     belong[x][y]=Rnd+1;
 58     p[k].x=x;p[k].y=y;
 59     cout<<dis[x][y]<<'\n';
 60 }
 61 void Kill(int x,int y,int type){
 62     if(p[x].GR==p[y].GR||p[x].DIE||p[y].DIE){
 63         printf("INVALID\n");
 64         return;
 65     }
 66     int dis=abs(p[y].x-p[x].x)+abs(p[y].y-p[x].y);
 67     if(dis>p[x].AD2||dis<p[x].AD1){
 68         printf("INVALID\n");
 69         return;
 70     }
 71     int rest=p[y].HP-p[x].AT,tp;
 72     if(rest<=0)tp=1;else tp=0;
 73     if(tp!=type){
 74         printf("INVALID\n");
 75         return;
 76     }
 77     p[y].HP=rest;
 78     cout<<rest<<'\n';
 79     if(tp){
 80         belong[p[y].x][p[y].y]=0;
 81         p[y].DIE=true;
 82     }
 83 }
 84 int main(){
 85     scanf("%d%d%d%d",&n,&m,&C,&E);
 86     for(int i=1;i<=n;i++)
 87         for(int j=1;j<=m;++j)
 88             scanf("%d",&G[i][j]);
 89     for(int i=1;i<=C;++i){
 90         p[i].HP=getint();p[i].AT=getint();p[i].MV=getint();
 91         p[i].AD1=getint();p[i].AD2=getint();
 92         p[i].x=getint();p[i].y=getint();
 93         p[i].GR=getint();
 94         belong[p[i].x][p[i].y]=p[i].GR+1;
 95     }
 96     char t1,t2;
 97     for(int i=1;i<=E;++i){
 98         t1=getchar();
 99         while(t1!='R'&&t1!='A'&&t1!='M'&&t1!='D')t1=getchar();
100         switch(t1){
101             case 'R':Rnd=getint();break;
102             case 'M':Move(id);break;
103             case 'D':Kill(id,getint(),1);break;
104             case 'A':{
105                 t2=getchar();
106                 if(t2=='c')id=getint();
107                 else Kill(id,getint(),0);
108                 break;
109             }
110         }
111     }
112     return 0;
113 }

我还会来做的,也许是很久很久之后。。。。

over

posted @ 2018-10-09 15:15  saionjisekai  阅读(63)  评论(0编辑  收藏  举报