codeforces 359E Neatness(DFS+构造)

Simon loves neatness. So before he goes to bed, Simon wants to complete all chores in the house.

Simon's house looks like a rectangular table consisting of n rows and n columns from above. All rows of the table are numbered from 1to n from top to bottom. All columns of the table are numbered from 1 to n from left to right. Each cell of the table is a room. Pair (x, y)denotes the room, located at the intersection of the x-th row and the y-th column. For each room we know if the light is on or not there.

Initially Simon is in room (x0, y0). He wants to turn off the lights in all the rooms in the house, and then return to room (x0, y0). Suppose that at the current moment Simon is in the room (x, y). To reach the desired result, he can perform the following steps:

  1. The format of the action is "1". The action is to turn on the light in room (x, y). Simon cannot do it if the room already has light on.
  2. The format of the action is "2". The action is to turn off the light in room (x, y). Simon cannot do it if the room already has light off.
  3. The format of the action is "dir" (dir is a character). The action is to move to a side-adjacent room in direction dir. The direction can be left, right, up or down (the corresponding dir is LRU or D). Additionally, Simon can move only if he see a light in the direction dir. More formally, if we represent the room, Simon wants to go, as (nx, ny), there shold be an integer k (k > 0), that room(x + (nx - x)k, y + (ny - y)k) has a light. Of course, Simon cannot move out of his house.

Help Simon, find the sequence of actions that lets him achieve the desired result.

Input

The first line contains three positive integers n, x0, y0 (2 ≤ n ≤ 500, 1 ≤ x0, y0 ≤ n).

Next n lines contain the description of rooms in the house. The i-th line contains n space-separated integers ai1, ai2, ..., ain. If numberaij equals zero, then room (i, j) has light off, and if number aij equals one, then room (i, j) has light on. It is guaranteed that at least one room has light on.

Output

If there is no desired sequence of actions, print "NO" (without the quotes). Otherwise, print "YES" (without the quotes) and the description of the required sequence of actions as a string. Note that you do not have to minimize the length of the sequence of actions but you shouldn't use more than 3·106 actions.

题目大意:给一个n*n的矩阵,每个矩阵有一个0或1,一个人一开始在点(x0, y0)。在某个点(x, y)的时候,可以向上下左右4个方向移动,可以移动当且仅当要移动的方向上至少有一个1。然后有3种操作,把0变成1、把1变成0、移动。问是否存在一种方案,使得从(x0, y0)出发,可以把所有的1变成0,然后回来(x0, y0),并输出这个方案。要求方案的操作次数不超过300W。

思路:暴力DFS,在某个点的时候,如果那个点是0,那么把它变成1,然后看一下4个方案能不能移动,若能移动,就走,等回溯到这个点的时候,把这个1变回0,然后回溯。若一次DFS之后,矩阵没有1,说明存在方案,然后输出这个方案(DFS的时候用数组存下来)。

我不会证明为什么是对的,反正是找不到反例。

至于方案长度的问题,每个点最多只会走一次,从代码可以看出每个点最多10次操作,250000个点的10倍,不到300W。

因为不是求最优解,会不会有很多多余的操作也就跟我没什么关系了……

代码(171MS):

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <queue>
 6 using namespace std;
 7 
 8 const int MAXN = 510;
 9 const int MAXL = 3000010;
10 
11 int mat[MAXN][MAXN];
12 bool vis[MAXN][MAXN];
13 char ans[MAXL];
14 int cnt, n, x0, y0;
15 
16 void dfs(int x, int y) {
17     vis[x][y] = true;
18     if(!mat[x][y]) {
19         mat[x][y] = 1;
20         ans[cnt++] = '1';
21     }
22     for(int i = x - 1; i > 0; --i) {
23         if(mat[i][y] == 1) {
24             if(!vis[x - 1][y]) {
25                 ans[cnt++] = 'U';
26                 dfs(x - 1, y);
27                 ans[cnt++] = 'D';
28             }
29             break;
30         }
31     }
32     for(int i = x + 1; i <= n; ++i) {
33         if(mat[i][y] == 1) {
34             if(!vis[x + 1][y]) {
35                 ans[cnt++] = 'D';
36                 dfs(x + 1, y);
37                 ans[cnt++] = 'U';
38             }
39             break;
40         }
41     }
42     for(int i = y - 1; i > 0; --i) {
43         if(mat[x][i] == 1) {
44             if(!vis[x][y - 1]) {
45                 ans[cnt++] = 'L';
46                 dfs(x, y - 1);
47                 ans[cnt++] = 'R';
48             }
49             break;
50         }
51     }
52     for(int i = y + 1; i <= n; ++i) {
53         if(mat[x][i] == 1) {
54             if(!vis[x][y + 1]) {
55                 ans[cnt++] = 'R';
56                 dfs(x, y + 1);
57                 ans[cnt++] = 'L';
58             }
59             break;
60         }
61     }
62     mat[x][y] = 0;
63     ans[cnt++] = '2';
64 }
65 
66 bool check() {
67     for(int i = 1; i <= n; ++i)
68         for(int j = 1; j <= n; ++j)
69             if(mat[i][j] == 1) return false;
70     return true;
71 }
72 
73 int main() {
74     scanf("%d%d%d", &n, &x0, &y0);
75     for(int i = 1; i <= n; ++i)
76         for(int j = 1; j <= n; ++j) scanf("%d", &mat[i][j]);
77     dfs(x0, y0);
78     ans[cnt++] = 0;
79     if(check()) printf("YES
%s
", ans);
80     else puts("NO");
81 }
View Code
原文地址:https://www.cnblogs.com/oyking/p/3405017.html