UVA_519
At first, the raw tracing and timeout occurred. Later, I thought of some pre-judgment, but it still timed out. After reading a post posted on the Forum, I said that the pre-judgment could not be saving, so I almost gave up the idea of continuing to think carefully about pre-judgment.
Then go to W. c. I thought of a more detailed pre-judgment, and then continued to think about it based on this idea, so I got more detailed pre-judgment, and finally AC, I feel that careful pre-judgment is a strong pruning.
During the pre-judgment, I mainly considered the following points:
① Globally, I/O numbers should be equal.
② The number of all F should be 2 * (M + N), but this is not detailed enough. It is not difficult for us to think about it carefully, the numbers of F in top and bottom are M, and the numbers of F in left and right are N, respectively.
③ Inspired by the separation of the four sides in the discussion ②, we can also think that the total IO numbers of left and right on the top and bottom sides should be equal. Likewise, the total I/O count of top and bottom on the left and right edges should be equal.
④ According to the size of the puzzle, the number of F on the corner should be limited. The limit may be called limitk. For example, if N and M are both 1, then the angle should have four F. If N and M have only one and only one is 1, then the angle should have three F, if N and M are not 1, the angle should have 2 F. The above analysis gives us two inspirations. First, F on the corner is the most. Therefore, if the number of F in a piece exceeds limitk, it is clear that there is no solution. Second, if the number of angles where the number of F is limited does not match the corresponding value, there is no solution. I didn't elaborate on every corner in my program. I just checked whether each piece of puzzle had a limit of F, in fact, you can also further refine whether each angle has only one according to the position of F.
#include<stdio.h>
#include<string.h>
#define MAXD 40
#define MAXN 10
int N, M, T, top[MAXD], right[MAXD], bottom[MAXD], left[MAXD];
int D[MAXN][MAXN], R[MAXN][MAXN], A[MAXD];
char b[MAXN], *str = "IFO";
void init()
{
int i, j, k;
T = N * M;
for(i = 0; i < T; i ++)
{
scanf("%s", b);
top[i] = strchr(str, b[0]) - str - 1;
right[i] = strchr(str, b[1]) - str - 1;
bottom[i] = strchr(str, b[2]) - str - 1;
left[i] = strchr(str, b[3]) - str - 1;
}
}
int place(int cur, int x, int y)
{
if(x == 0 && top[cur] != 0)
return 0;
if(x != 0 && top[cur] + D[x - 1][y] != 0)
return 0;
if(y == M - 1 && right[cur] != 0)
return 0;
if(y != M - 1 && right[cur] == 0)
return 0;
if(x == N - 1 && bottom[cur] != 0)
return 0;
if(x != N - 1 && bottom[cur] == 0)
return 0;
if(y == 0 && left[cur] != 0)
return 0;
if(y != 0 && left[cur] + R[x][y - 1] != 0)
return 0;
return 1;
}
int dfs(int x, int y)
{
int i, j, k;
if(y == M)
++ x, y = 0;
if(x == N)
return 1;
for(i = 0; i < T; i ++)
if(!A[i] && place(i, x, y))
{
A[i] = 1;
D[x][y] = bottom[i], R[x][y] = right[i];
if(dfs(x, y + 1))
return 1;
A[i] = 0;
}
return 0;
}
int check()
{
int i, j, k, limitk, upcnt, downcnt, leftcnt, rightcnt;
int iototal, ioup, iodown, ioleft, ioright, num;
iototal = ioup = iodown = ioleft = ioright = 0;
upcnt = downcnt = leftcnt = rightcnt = num = 0;
if(N == 1 && M == 1)
limitk = 4;
else if(N == 1 || M == 1)
limitk = 3;
else
limitk = 2;
for(i = 0; i < T; i ++)
{
k = 0;
if(top[i] == 0)
++ upcnt, ++ k, ioup = ioup + (left[i] + right[i]);
if(right[i] == 0)
++ rightcnt, ++ k, ioright = ioright + (top[i] + bottom[i]);
if(bottom[i] == 0)
++ downcnt, ++ k, iodown = iodown + (left[i] + right[i]);
if(left[i] == 0)
++ leftcnt, ++ k, ioleft = ioleft + (top[i] + bottom[i]);
if(k > limitk)
return 0;
if(k == limitk)
++ num;
iototal = iototal + (top[i] + right[i] + bottom[i] + left[i]);
}
if(limitk == 2 && num != 4)
return 0;
if(limitk == 3 && num != 2)
return 0;
if(limitk == 4 && num != 1)
return 0;
if(upcnt != M || downcnt != M || leftcnt != N || rightcnt != N)
return 0;
if(iototal != 0 || ioup != 0 || ioright != 0 || iodown != 0 || ioleft != 0)
return 0;
return 1;
}
void solve()
{
if(!check())
{
printf("NO\n");
return ;
}
memset(A, 0, sizeof(A));
if(dfs(0, 0))
printf("YES\n");
else
printf("NO\n");
}
int main()
{
for(;;)
{
scanf("%d%d", &N, &M);
if(!N && !M)
break;
init();
solve();
}
return 0;
}