题目链接:http://codeforces.com/problemset/problem/606/B
题意:花了好久才读懂,感觉好反人类。。。大概意思是:给定一个x*y的矩形,和一个机器人的初始位置(x0,y0)。以向下为x轴正方向,向右为y轴正方向。现在要对这个机器人进行多次测试。每次测试,会在矩形的某个位置有一个矿井。所以一共要进行x*y次测试,每次测试,矿井会出现在一个之前的测试没有出现过的地方,而机器人的初始位置保持不变(即为(x0,y0))。
每次测试,机器人会沿一个给定的字符串走,字符串只可能包括'L', 'R', 'U', 'D',分别代表向左,向右,向上,向下。当然,如果机器人不能沿所给的方向走(就是走到了边缘),机器人会呆在原地一次。每次测试,机器人都按这个给定的字符串走。当机器人走到和矿井所在的位置重合时,机器人会爆炸,当机器人恰好走完这个字符串之后,机器人也会爆炸。
现在想知道,机器人在走了第k步后(0<=k<=n,其中n为字符串的长度),有多少种测试情况会使机器人在恰好走了k步之后就爆炸了?
解答:首先是走了0步的时候,机器人呆在原地,只有一种情况会使机器人爆炸,就是矿井和初始位置重合的情况。
然后就是机器人开始走,分为两种,一种是当前这步是最后一步,另一种是当前这步是最后一步。
先讨论不是最后一步的情况,又分为两种,一种是这一步走到的位置之前没有走到过,这种就只有一种情况会使机器人爆炸,就是这个位置和矿井位置重合的情况。
另一种就是这一步走到的位置在之前走到过了,这种是没有测试情况会使机器人在这一步之后爆炸的,因为当前没有到最后一步,要爆炸只可能是当前位置与矿井位置重合,但是如果当前位置与矿井位置重合的话,在第一次走到这个位置的时候,机器人就已经爆炸了,所以情况数为0。
继续讨论就是当前这一步是最后一步的情况。首先,走完这步后,所有矿井位置与所走过的任何一个位置都不重合的测试情况都会使机器人爆炸(这个是走完这个字符串之后,机器人自动爆炸的原理),另一种就是矿井位置与这一步走完后的位置重合,但是也分两种,一种是第一次走到这个位置,这种的话,这个情况是属于答案要求的。另一种就是之前已经走到过这个位置了,这个情况就不属于答案要求了(因为机器人在第一次走到这个位置时,就会爆炸)。
所以我们可以一边去进行机器人一步一步的行走,同时记录有多少个位置机器人还没有走到过就好。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; bool grid[505][505]; char str[100005]; int x, y, xi, yi, n, s, xo, yo; bool walk(char c) { bool flag = false; switch (c)//进行了正确的行走方法 { case'R': if (yi < y) ++yi; break; case'U': if (xi > 1) --xi; break; case'D': if (xi < x) ++xi; break; case'L': if (yi > 1) --yi; break; } //printf("debug %d %d ", xi, yi); if (grid[xi][yi] == 0) { flag = true;//只关心是否走到了新的之前没走过的点 --s; } grid[xi][yi] = 1; return flag; } int main() { //freopen("input.txt", "r", stdin); memset(grid, 0, sizeof(bool) * 505 * 505); scanf("%d%d%d%d", &x, &y, &xo, &yo); scanf("%s", str); n = strlen(str); s = x*y; xi = xo; yi = yo; --s; grid[xo][yo] = 1; printf("1 "); for (int i = 0; i < n - 1; ++i) { printf("%d ", walk(str[i])); } if (walk(str[n - 1])) printf("%d\n", s + 1); else printf("%d\n", s); //system("pause"); //while (1); return 0; }