您的位置:首页 > 其它

zoj 1008 Gnome Tetravex

2015-07-23 22:49 246 查看
题目链接

题意 有一些卡片上下左右均有数字,要求将这些卡片拼成正方形,并且相接部分数字相同:

思路:dfs深搜,但要注意如果直接暴力的话,深搜是一个全排列问题,计算量最大是为25!,这个数字是非常大的,但如果对卡片进行分类,即上下左右均相等的卡片分成一类,这样全排列的计算量将大大减小,

这里我测试了两种思路稍有不同的代码,如下:

经测试第二种稍微快一点,应该是是因为跳出的较快, 总的来说对dfs的返回及恢复初始值问题是比较难理解透彻的,稍不注意就超时或者其他各种问题

此外本体还应注意一些换行及空格问题,oj无情啊。。。

#include<iostream>
#include<stdio.h>
using namespace std;
int n,q;
int isqure[25][4];//储存卡片的种类
int icount[25];//储存每种卡片的数量
int itable[25];//存储各位置放置的卡片种类
int dfs(int num)
{
int i;
if(num==n*n)//最后一个卡片已经放置完成,返回
return 1;
for(i=0;i<q;i++)//检查每一个卡片能否放置
{
if(icount[i]==0)//该种类卡片无剩余,搜索下一个
continue;
if(num%n!=0)//不是最左边一行,检查与左边连接处数字是否相同
if(isqure[itable[num-1]][1]!=isqure[i][3])
continue;
if(num>=n)不是最上面一行,检查与上面连接处数字是否相同
if(isqure[itable[num-n]][2]!=isqure[i][0])
continue;
itable[num]=i;//标记该位置放置的卡片种类
icount[i]--;//卡片数量减1
if(dfs(num+1)==1) return 1; //注意理解这里的返回与卡片数量的恢复,
icount[i]++;
}
return 0;
}

int main()
{
//freopen("in.txt","r",stdin);
int ans=1;
while(scanf("%d",&n)!=EOF&&n)
{
q=0;//卡片的种类
int top,right,bottm,left;
for(int i=0;i<n*n;i++)
{
scanf("%d%d%d%d",&top,&right,&bottm,&left);
int j=0;
for(j=0;j<q;j++)//检查输入的卡片是否已将存过,若存过,该种类数量加1
{
if(isqure[j][0]==top && isqure[j][1]==right && isqure[j][2]==bottm && isqure[j][3]==left)
{
icount[j]++;
break;
}
}
if(j==q)//如果没存过该种卡片,建立新的卡片种类,并使其初始值为1,同时卡片种类q加1
{
isqure[j][0]=top;
isqure[j][1]=right;
isqure[j][2]=bottm;
isqure[j][3]=left;
q++;
icount[j]=1;
}
}
int flag=dfs(0);
if(ans-1)
printf("\n");
printf("Game %d: ",ans++);
if(flag)
printf("Possible\n");
else
printf("Impossible\n");

}
}


#include<iostream>
#include<stdio.h>
using namespace std;
int n,q,flag;
int isqure[25][4];
int icount[25];
int itable[25];
void dfs(int num)
{
int i;
if(flag)return;//这里如果没有一个检查过程,本解法将会超时
if(num==n*n)
{
flag=1;
return ;
}

for(i=0;i<q;i++)
{
if(icount[i]==0)
continue;
if(num%n!=0)
if(isqure[itable[num-1]][1]!=isqure[i][3])
continue;
if(num>=n)
if(isqure[itable[num-n]][2]!=isqure[i][0])
continue;
itable[num]=i;
icount[i]--;
//if(dfs(num+1)==1) return 1;
dfs(num+1);
icount[i]++;
}
return ;
}

int main()
{
//freopen("in.txt","r",stdin);
int ans=1;
while(scanf("%d",&n)!=EOF&&n)
{
flag=q=0;
int top,right,bottm,left;
for(int i=0;i<n*n;i++)
{
scanf("%d%d%d%d",&top,&right,&bottm,&left);
int j=0;
for(j=0;j<q;j++)
{
if(isqure[j][0]==top && isqure[j][1]==right && isqure[j][2]==bottm && isqure[j][3]==left)
{
icount[j]++;
break;
}
}
if(j==q)
{
isqure[j][0]=top;
isqure[j][1]=right;
isqure[j][2]=bottm;
isqure[j][3]=left;
q++;
icount[j]=1;
}
}
dfs(0);
if(ans-1)
printf("\n");
printf("Game %d: ",ans++);
if(flag)
printf("Possible\n");
else
printf("Impossible\n");

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: