2013-07-22 20:23:14Morris

[UVA][剪枝] 1098 - Robots on Ice

Inspired by the ice sculptures in Harbin, the members of the programming team from Arctic University of Robotics and Automata have decided to hold their own ice festival when they return home from the contest. They plan to harvest blocks of ice from a nearby lake when it freezes during the winter. To make it easier to monitor the thickness of the ice, they will lay out a rectangular grid over the surface of the lake and have a lightweight robot travel from square to square to measure ice thickness at each square in the grid. Three locations in the grid are specified as ``check-in" points and the robot is supposed to radio a progress report from these points when it is one-fourth, one-half, and three-fourths of the way through its tour of inspection. To avoid unnecessary wear and tear on the surface of the ice, the robot must begin its tour of the grid from the lower left corner, designated in (row,column) coordinates as (0,0), visiting every other grid location exactly once and ending its tour in row 0, column 1. Moreover, if there are multiple tours that the robot can follow, then a different one is to be used each day. The robot is able to move only one square per time step in one of the four compass directions: north, south, east, or west.


You are to design a program that determines how many different tours are possible for a given grid size and a sequence of three check-in points. For example, suppose the lake surface is marked off in a 3 x 6 grid and that the check-in points, in order of visitation, are (2,1), (2,4), and (0,4). Then the robot must start at (0,0) and end at (0,1) after visiting all 18 squares. It must visit location (2,1) on step 4 (= $ lfloor$18/4$ rfloor$), location (2,4) on step 9 (= $ lfloor$18/2$ rfloor$), and location (0,4) on step 13 (= $ lfloor$3 x 18/4$ rfloor$). There are just two ways to do this (see Figure 8). Note that when the size of the grid is not divisible by 4, truncated division is used to determine the three check-in times.

epsfbox{p4793.eps}

Note that some configurations may not permit any valid tours at all. For example, in a 4 x 3 grid with check-in sequence (2,0), (3,2), and (0,2), there is no tour of the grid that begins at (0,0) and ends at (0,1).

Input 

The input contains several test cases. Each test case begins with a line containing two integers m and n, where 2$ le$m, n$ le$8, specifying the number of rows and columns, respectively, in the grid. This is followed by a line containing six integer values r1, c1, r2, c2, and r3, c3, where 0$ le$ri < m and 0$ le$ci < n for i = 1, 2, 3.

Following the last test case is a line containing two zeros.

Output 

Display the case number, beginning at 1, followed by the number of possible tours that begin at row 0, column 0, end at row 0, column 1, and visit row ri, column ci at time $ lfloor$i x m x n/4$ rfloor$ for i = 1, 2, 3. Follow the format of the sample output.

Sample Input 

3 6 
2 1 2 4 0 4 
4 3 
2 0 3 2 0 2 
0 0

Sample Output 

Case 1: 2 
Case 2: 0

題目描述:

給定起點終點,以及三個點要在指定步數恰好抵達,並且經過所有的點。
問有多少種走法。

題目解法:


剪枝方法非常多,有最短路內還不能走到該點,以及在指定步數前經過該點,又或者將圖形剖成兩半。

剖半的動作不能使用 BFS 去檢查,不然會太慢。

想法是看九宮格,把接下來要走的點放中間,查看是否分成兩個區域,看法是順時針,如果有兩個以上的區域被分開,即會產生 4 個以上的邊界(走過與沒走過)。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int n, m, r1, r2, r3, r4, c1,c2, c3, c4;
int step1, step2, step3, step4;
int used[10][10], ret;
int divid2(int x, int y) {
static int v[9], i, j;
v[0] = x-1 < 0 || y-1 < 0 || used[x-1][y-1];
v[1] = x-1 < 0 || used[x-1][y];
v[2] = x-1 < 0 || y+1 >= m || used[x-1][y+1];
v[3] = y+1 >= m || used[x][y+1];
v[4] = x+1 >= n || y+1 >= m || used[x+1][y+1];
v[5] = x+1 >= n || used[x+1][y];
v[6] = x+1 >= n || y-1 < 0 || used[x+1][y-1];
v[7] = y-1 < 0 || used[x][y-1];
v[8] = v[0];
for(i = 0, j = 0; i < 8; i++)
if(v[i] != v[i+1])
j++;
return j >= 4;
}
void dfs(int step, int x, int y) {
if(step < step1 && used[r1][c1]) return;
if(step < step2 && used[r2][c2]) return;
if(step < step3 && used[r3][c3]) return;
if(step < step4 && used[r4][c4]) return;
if(step == step1 && (x != r1 || y != c1))
return;
if(step == step2 && (x != r2 || y != c2))
return;
if(step == step3 && (x != r3 || y != c3))
return;
if(step == step4 && (x != r4 || y != c4))
return;
if(step == step4) {ret++;return;}
if(step < step1 && step+abs(x-r1)+abs(y-c1) > step1)
return;
if(step < step2 && step+abs(x-r2)+abs(y-c2) > step2)
return;
if(step < step3 && step+abs(x-r3)+abs(y-c3) > step3)
return;
if(step < step4 && step+abs(x-r4)+abs(y-c4) > step4)
return;
if(divid2(x, y))
return;
used[x][y] = 1;
if(x+1 < n && !used[x+1][y]) dfs(step+1, x+1, y);
if(x-1 >= 0 && !used[x-1][y]) dfs(step+1, x-1, y);
if(y+1 < m && !used[x][y+1]) dfs(step+1, x, y+1);
if(y-1 >= 0 && !used[x][y-1]) dfs(step+1, x, y-1);
used[x][y] = 0;
}
int main() {
int cases = 0;
while(scanf("%d %d", &n, &m) == 2 && n+m) {
scanf("%d %d", &r1, &c1), step1 = 1*n*m/4;
scanf("%d %d", &r2, &c2), step2 = 2*n*m/4;
scanf("%d %d", &r3, &c3), step3 = 3*n*m/4;
r4 = 0, c4 = 1, step4 = n*m;
memset(used, 0, sizeof(used));
ret = 0;
dfs(1, 0, 0);
printf("Case %d: %d\n", ++cases, ret);
}
return 0;
}
/*
8 8
2 1 2 4 0 4
8 8
2 0 3 2 0 2
*/