受到哈尔滨的冰雕的启发,北极大学机器人和自动化专业的程序员们决定在他们结束比赛回家的时候举行他们自己的冰雪节。附近有一片湖,当冬天湖结冰时,他们计划从中取一些冰块。为了更容易地监测冰的厚度,他们将在湖面上一个矩形网格区域内放一个轻量级的机器人,让它经过网格中的每一个方格以测量冰块的厚度。网格中的3个地方被指定为登记点,机器人应该在它完成全程的四分之一、二分之一、四分之三时分别在这些指定的地方无线电报告工作的进展。为了避免冰面不必要的磨损,机器人必须从网格的左下角(按照(行,列)定义为(0,0))开始,访问每个格子恰好一次,最后到(0,1)结束。此外,如果机器人可以按照多条不同的路径行走,那么每天按一条不同的路走。机器人每步只能向东、南、西、北四个方向中的一个移动一格。
你需要设计一个程序,对于给定网格的尺寸和一个3个登记点的序列,确定有多少种不同的行走路径。举个例子,假设湖面上标记了一个3*6的网格,检查点依次为(2,1)、(2,4)、(0,4)。那么机器人必须从(0,0)开始经过所有18个方格,到(0,1)结束,它必须在第4(=[18/4])步到达(2,1),在第9(=[2*18/4])步到达(2,4),在第13(=[3*18/4])步到达(0,4)。只有2条路径满足条件。请注意,当网格的大小不能被4整除,下取整决定到达3次登记点的时间。
请注意,有一些情况可能没有可行的路径。例如,在一个4*3的网格中,登记点分别为(2,0)、(3,2)和(0,2),没有从(0,0)开始在(0,1)结束的路径满足条件。
输入格式
输入包含几组测试数据。每组测试数据,第一行包含两个整数m,n(2<=m,n<=8),表示网格的行数和列数。接下来一行包含6个整数r1,c1,r2,c2,r3,c3 (对于每一个i=1,2,3满足0<=ri<m,0<=ci<n)。最后一行包含两个0表示结束。
输出格式
对于每组测试数据,输出测试数据编号和满足从(0,0)出发到(0,1)结束并且在[i*m*m/4]步到达(ri,ci)的路径的条数,按照样例中的输出格式输出。
【样例输入】
3 6
2 1 2 4 0 4
4 3
2 0 3 2 0 2
0 0
【样例输出】
Case 1: 2
Case 2: 0
数据规模和约定
测试数据组数<=10
细节完善:
第i个检查点的坐标为(x[i],y[i]),访问时间为c[i],定义mp来存储网格中的检查点序号,定义check作为格子的访问标记,定义bool函数判断四周未走过的格子是否被截成两部分。递归计算可行的路径数(当前格为(x1,y1),步数为dep,待检查的点为c1),走完了可达c1检查点的时间。若到达c1检查点,则准备访问下一个检查点,否则剪枝,没到时间就走到了检查点上就剪枝,若(tx,ty)在界内且未被访问,且4周未走过的格子未被其截成2部分,则访问该格子。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=11;
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int n,m,t;
int x[5],y[5],c[5];
int mp[maxn][maxn];
bool check[maxn][maxn];
int ans;
int b[4];
bool cut(int x,int y){
for(int i=0;i<4;i++){
int tx=x+dir[i][0];
int ty=y+dir[i][1];
b[i]=((tx>=0)&&tx<n&&ty>=0&&ty<m&&!check[tx][ty]);
}
return (b[0]&&b[2]&&!b[1]&&!b[3])||(!b[0]&&!b[2]&&b[1]&&b[3]);
}
void dfs(int x1,int y1,int c1,int dep){
if(dep==c[c1]){
if(mp[x1][y1]==c1)
c1++;
else
return;
}
else if(mp[x1][y1]>0)
return;
if(dep==t){
ans++;
return;
}
if(abs(x[c1]-x1)+abs(y[c1]-y1)>c[c1]-dep)
return;
for(int i=0;i<4;i++){
int tx=x1+dir[i][0];
int ty=y1+dir[i][1];
if(tx>=0&&tx<n&&ty>=0&&ty<m&&!check[tx][ty]&&!cut(tx,ty)){
check[tx][ty]=1;
dfs(tx,ty,c1,dep+1);
check[tx][ty]=0;
}
}
}
int main(){
int ks=0;
while(scanf("%d %d",&n,&m)!=EOF){
if(n==0&&m==0)
break;
memset(mp,0,sizeof(mp));
t=n*m;
for(int i=1;i<=3;i++){
cin>>x[i]>>y[i];
c[i]=i*t/4;
mp[x[i]][y[i]]=i;
}
x[4]=0;
y[4]=1;
c[4]=t;
mp[0][1]=4;
ans=0;
memset(check,0,sizeof(check));
check[0][0]=1;
dfs(0,0,1,1);
printf("Case %d: %d\n",++ks,ans);
}
return 0;
}