Description
给出一个n×mn\times mn×m的网格,每个格子可以一步走向上下左右这四个相邻格子中的一个,给出kkk个传送路径,表示从一个点可以一步传送到另一个点,现在从(1,1)(1,1)(1,1)出发,要求用最少步数经过所有点一遍后回到(1,1)(1,1)(1,1)点,输出最少步数
Input
第一行一整数TTT表示用例组数,每组用例首先三个整数n,m,kn,m,kn,m,k,之后kkk行每行输入四个整数x1,y1,x2,y2x_1,y_1,x_2,y_2x1,y1,x2,y2表示(x1,y1),(x2,y2)(x_1,y_1),(x_2,y_2)(x1,y1),(x2,y2)两点之间有一个传送路径
(1≤T≤20,0≤k≤10,2≤n,m≤100,1≤n⋅m≤100)(1\le T\le 20,0\le k\le 10,2\le n,m\le 100,1\le n\cdot m\le 100)(1≤T≤20,0≤k≤10,2≤n,m≤100,1≤n⋅m≤100)
Output
输出最少步数
Sample Input
3
2 2 1
1 1 2 2
3 3 1
1 1 3 3
3 3 0
Sample Output
4
9
10
Solution
若n,mn,mn,m有一个为偶数时可以n⋅mn\cdot mn⋅m步就遍历所有点回到(1,1)(1,1)(1,1)点,此时即为最少步数
当n,mn,mn,m全部为奇数时,由于此时距(1,1)(1,1)(1,1)哈密顿距离为偶数的点的个数比距(1,1)(1,1)(1,1)哈密顿距离为奇数的点多两个,若以该点到(1,1)(1,1)(1,1)的哈密顿距离奇偶性将所有点分成奇点和偶点,那么每次只会从一个奇点到偶点,或者从一个偶点到奇点,故走到最后会剩下两个偶点,此时必然需要从一个偶点走到一个之前走过的奇点再走到最后一个偶点,此时步数最少为n⋅m+1n\cdot m+1n⋅m+1,而多出的kkk条路径使得有可能让步数减一,即若某条路径是从偶点到达偶点的,那么有一步就可以不从偶点走到奇点,而是通过该条路径走向另一个偶点,使得最少步数为n×mn\times mn×m,故只要判断是否存在一条连接两个不同偶点的路径即可
Code
#include<cstdio>
using namespace std;
#define maxn 100
int T,n,m,k,a[maxn][4];
int check(int x,int y,int x1,int y1)
{
if(x==x1&&y==y1)return 0;
int s=x-1+y-1,t=x1-1+y1-1;
if(s%2==0&&t%2==0)return 1;
return 0;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++)
for(int j=0;j<4;j++)
scanf("%d",&a[i][j]);
if(n%2==0||m%2==0)printf("%d\n",n*m);
else
{
int flag=0;
for(int i=1;i<=k;i++)
if(check(a[i][0],a[i][1],a[i][2],a[i][3]))
{
flag=1;
break;
}
int ans=n*m+1-flag;
printf("%d\n",ans);
}
}
return 0;
}