武林 HDU - 1107
题目链接:https://vjudge.net/problem/HDU-1107
注意:题目中只有两个不同门派的人在同一个地方才能对决,其他情况都不能对决。
还有,这步的有效的攻击只有走到下一步之后才生效,所以会出现样例1和样例2的情况。
代码有注释,便于理解,这理我说一下vis[][][]数组的用处。
vis[x][x][1] 表示少林寺人的编号。
vis[x][x][2] 表示武当派人的编号。
vis[x][x][3] 表示峨眉派人的编号。
vis[x][x][4] 表示一个门派是否有超过两个人。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <map> 7 #include <cmath> 8 #include <iomanip> 9 using namespace std; 10 11 typedef long long LL; 12 #define inf (1LL << 25) 13 #define rep(i,j,k) for(int i = (j); i <= (k); i++) 14 #define rep__(i,j,k) for(int i = (j); i < (k); i++) 15 #define per(i,j,k) for(int i = (j); i >= (k); i--) 16 #define per__(i,j,k) for(int i = (j); i > (k); i--) 17 18 const int N = 20; 19 int vis[N][N][10]; 20 int steps; 21 22 struct People{ 23 24 char c; //门派 25 int tot;//标记 26 int x,y;//坐标 27 int dir;//方向 正负1来方便判断 28 int nx,wx,sx; 29 30 int att(){//攻击 31 if(c == 'S') return (0.5 * nx + 0.5 * wx) * (sx * 1.0 + 10) /100; 32 else if(c == 'W') return (0.8 * nx + 0.2 * wx) * (sx * 1.0 + 10) /100; 33 else if(c == 'E') return (0.2 * nx + 0.8 * wx) * (sx * 1.0 + 10) /100; 34 } 35 36 //被攻击 37 void is_att(int x) { sx -= x;} 38 39 //移动 40 void mv(){ 41 if(c == 'S'){ 42 if(!(x + dir >= 1 && x + dir <= 12)) dir = -dir; 43 x += dir; 44 } 45 else if(c == 'W'){ 46 if(!(y + dir >= 1 && y + dir <= 12)) dir = -dir; 47 y += dir; 48 } 49 else if(c == 'E'){ 50 int xx = x + dir; 51 int yy = y + dir; 52 if(!(xx >= 1 && xx <= 12 && yy >= 1 && yy <= 12)) dir = -dir; 53 if(x + dir >= 1 && x + dir <= 12 && y + dir >= 1 && y + dir <= 12) x += dir, y += dir; 54 } 55 } 56 57 //写下标记 58 void vis_w(){ 59 if(c == 'S'){ 60 if(vis[x][y][1] == 0) vis[x][y][1] = tot; 61 else vis[x][y][4] = 1; 62 } 63 else if(c == 'W'){ 64 if(vis[x][y][2] == 0) vis[x][y][2] = tot; 65 else vis[x][y][4] = 1; 66 67 } 68 else if(c == 'E'){ 69 if(vis[x][y][3] == 0) vis[x][y][3] = tot; 70 else vis[x][y][4] = 1; 71 } 72 } 73 74 //擦除标记 75 void vis_e(){ 76 rep(i,1,4) vis[x][y][i] = 0; 77 } 78 79 }p[1010]; 80 bool died[1010]; //该编号的人是否死亡 81 int pl;//人数 82 83 void work(){ 84 85 rep(q,1,steps){ 86 rep(i,1,12) rep(j,1,12){ 87 88 if(vis[i][j][4] == 1) continue; //一个门派超过两个人 89 int a = 0,b = 0,num = 0; 90 rep(p,1,3) if(vis[i][j][p] != 0){ 91 num++; 92 if(!a) a = vis[i][j][p]; 93 else b = vis[i][j][p]; 94 } 95 96 if(num != 2) continue; //不是两个人 97 98 int w1 = p[a].att(); 99 int w2 = p[b].att(); 100 p[a].is_att(w2); 101 p[b].is_att(w1); 102 } 103 104 rep(o,1,pl) if(!died[o]){ 105 p[o].vis_e();//擦除标记 106 if(p[o].sx <= 0) died[o] = true; 107 } 108 109 rep(o,1,pl) if(!died[o]){ 110 p[o].mv(); 111 p[o].vis_w();//标记 112 } 113 } 114 } 115 116 void print(){ 117 118 int m[4] = {0}; 119 int t[4] = {0}; 120 121 rep(o,1,pl){ 122 if(died[o]) continue; 123 124 if(p[o].c == 'S') m[1]++, t[1] += p[o].sx; 125 else if(p[o].c == 'W') m[2]++, t[2] += p[o].sx; 126 else if(p[o].c == 'E') m[3]++, t[3] += p[o].sx; 127 } 128 129 cout << m[1] << ' ' << t[1] << endl; 130 cout << m[2] << ' ' << t[2] << endl; 131 cout << m[3] << ' ' << t[3] << endl; 132 cout << "***" << endl; 133 } 134 135 int main(){ 136 137 ios::sync_with_stdio(false); 138 cin.tie(0); 139 140 int T; 141 cin >> T; 142 char in; 143 while(T--){ 144 145 pl = 0; 146 rep(i,1,1005) died[i] = false; 147 rep(i,1,15) rep(j,1,15) rep(k,1,4) vis[i][j][k] = 0; 148 cin >> steps; 149 150 while(cin >> in){ 151 if(in == '0'){ 152 break; 153 } 154 155 ++pl; 156 p[pl].c = in; 157 p[pl].tot = pl; 158 p[pl].dir = 1; 159 cin >> p[pl].x >> p[pl].y >> p[pl].nx >> p[pl].wx >> p[pl].sx; 160 p[pl].vis_w(); 161 } 162 work(); 163 print(); 164 } 165 166 getchar(); getchar(); 167 return 0; 168 }
1