uva519 Puzzle (II)

5 篇文章 0 订阅

这道题折腾了接近两天时间,快把我逼疯了,不过收获巨大!!

我的第一个版本写的超烂,虽然写的很细致,如果能ac的话效率应该会很高,但的很乱,冗余度也很高,在加上自己的渣水平,debug了一天也没ac,只好推倒重来。

反思了一下,自己在写第一个版本的时候,完全是为了追求速度,几乎放弃了对代码可读性及风格的要求,这样做真是得不偿失,以后一定要注意!下面会附上第一个版本的代码。

相比之下,第二个版本由于吸取了教训,当然也包括借鉴别人的代码,无论是代码可读性(或者叫可调试性),还是效率,都要更高。

先说一下pruning:

1、四个方向上 F O I 都要满足特殊要求,O I要一一对应。

2、先用qsort对piece进行排列,这样做的便于后面dfs剪枝。

3、dfs的时候,如果一个piece不能放在这个位置,就把它记录下来,如果碰到相同的piece就continue,这个剪枝非常重要,基本上决定了会不会超时。

也基本掌握了stdlib里qsort的用法(在这里也卡了好久,基本功是硬伤啊。。),主要就是cmp函数的写法:对于cmp函数,如果 比较函数返回大于0,qsort就认为 a>b , 如果比较函数返回等于0 qsort就认为a 和b 这两个元素相等,返回小于零 qsort就认为 a<b。

这个和stl里的cmp不同,stl里的只要求cmp函数能判断小于关系,不过我尝试了一下好像stl里的sort不适合排列字符串。

最重要的收获其实是,做题时,最重要的是心态,心态好,一切都好说,如果只是为了做题而做题,或者心情暴躁不安,基本上就是在磨时间,以后一定要做出改变

另外,从这道题开始,我也准备放弃vc改用codeblocks,因为调的过程中发现了它们的一个不同:我在memset数组时,数值写大了,结果vc下没有影响其他变量而codeblocks影响了。。。这虽然主要是自己的错,但还是换过避免一些问题吧。


版本一:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10
using namespace std;

char corner[4][10],border[4][N-2][10],center[(N-2)*(N-2)][10],vis[5][(N-2)*(N-2)],input[N][10],area[N][N][10],visit[N][N];
int n,m,corners1,corners2,corners3,corners4,borders1,borders2,borders3,borders4,centers;
int ok;

int judge1()
{
	int i,j,help[8]={0,1,2,3,4,5,6,7};
	for(i=0;i<m;i++)
		if(input[i][0]!='F'||input[i][2]!='F')
			return 0;
	//qsort(input,m,5,cmp);
	do
	{
		if(input[help[0]][0]=='F'&&input[help[0]][2]=='F'&&input[help[0]][3]=='F'&&input[help[m-1]][0]=='F'&&input[help[m-1]][2]=='F'&&input[help[m-1]][1]=='F')
		{
			for(i=1;i<m;i++)
			{
				if(!(input[help[i-1]][1]=='O'&&input[help[i]][3]=='I'||input[help[i-1]][1]=='I'&&input[help[i]][3]=='O'))
					break;
			}
			if(i==m)
				return 1;
		}
	}while(next_permutation(help,help+m));
	return 0;
}
int judge2()
{
	//printf("test");
	int i,j,help[8]={0,1,2,3,4,5,6,7};
	for(i=0;i<n;i++)
		if(input[i][1]!='F'||input[i][3]!='F')
			return 0;
		//qsort(input,n,5,cmp);
		do
		{
			if(input[help[0]][0]=='F'&&input[help[0]][1]=='F'&&input[help[0]][3]=='F'&&input[help[n-1]][1]=='F'&&input[help[n-1]][2]=='F'&&input[help[n-1]][3]=='F')
			{
				for(i=1;i<n;i++)
				{
					if(!(input[help[i-1]][2]=='O'&&input[help[i]][0]=='I'||input[help[i-1]][2]=='I'&&input[help[i]][0]=='O'))
						break;
				}
				//printf("test%d ",i);
				if(i==n)
					return 1;
			}
		}while(next_permutation(help,help+n));
		return 0;
}

int nextx(int x,int y)
{
	if(y==m-1)
		return x+1;
	else
		return x;
}

int nexty(int y)
{
	if(y==m-1)
		return 0;
	else
		return y+1;
}

int judge(int x,int y,char p[5])
{
	int i,j;
	 if(x==0)
	 {
		 int vector[3][2]={{0,1},{1,0},{0,-1}},flag[3][2]={{3,1},{0,2},{1,3}};
		 for(i=0;i<3;i++)
		 {
			 if(visit[x+vector[i][0]][y+vector[i][1]])
			 {
				 if(!(area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='I'&&p[flag[i][1]]=='O'||area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='O'&&p[flag[i][1]]=='I'))
					 return 0;
			 }
		 }
	return 1;
	 }
	 else if(y==m-1)
	 {
		 int vector[3][2]={{-1,0},{1,0},{0,-1}},flag[3][2]={{2,0},{0,2},{1,3}};
		 for(i=0;i<3;i++)
		 {
			 if(visit[x+vector[i][0]][y+vector[i][1]])
			 {
				 if(!(area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='I'&&p[flag[i][1]]=='O'||area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='O'&&p[flag[i][1]]=='I'))
					 return 0;
			 }
		 }
	return 1;
	 }
	 else if(x==n-1)
	 {
		 int vector[3][2]={{-1,0},{0,1},{0,-1}},flag[3][2]={{2,0},{3,1},{1,3}};
		 for(i=0;i<3;i++)
		 {
			 if(visit[x+vector[i][0]][y+vector[i][1]])
			 {
				 if(!(area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='I'&&p[flag[i][1]]=='O'||area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='O'&&p[flag[i][1]]=='I'))
					 return 0;
			 }
		 }
	return 1;
	 }
	 else if(y==0)
	 {
		 int vector[3][2]={{-1,0},{0,1},{1,0}},flag[3][2]={{2,0},{3,1},{0,2}};
		 for(i=0;i<3;i++)
		 {
			 if(visit[x+vector[i][0]][y+vector[i][1]])
			 {
				 if(!(area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='I'&&p[flag[i][1]]=='O'||area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='O'&&p[flag[i][1]]=='I'))
					 return 0;
			 }
		 }
		return 1;
	 }
	 else
	 {
		 int vector[4][2]={{-1,0},{0,1},{1,0},{0,-1}},flag[4][2]={{2,0},{3,1},{0,2},{1,3}};
		 for(i=0;i<4;i++)
		 {
			if(visit[x+vector[i][0]][y+vector[i][1]])
			{
				if(!(area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='I'&&p[flag[i][1]]=='O'||area[x+vector[i][0]][y+vector[i][1]][flag[i][0]]=='O'&&p[flag[i][1]]=='I'))
					 return 0;
			}
		 }
		 return 1;
	 }
}

void dfs(int x,int y)
{
	if(ok==1)
		return ;
	if(x==n&&y==0)
	{      //2*2以及其他的情况
			if((area[0][0][1]=='I'&&area[0][1][3]=='O'||area[0][0][1]=='O'&&area[0][1][3]=='I')
				&&(area[0][0][2]=='I'&&area[1][0][0]=='O'||area[0][0][2]=='O'&&area[1][0][0]=='I')
				&&(area[0][m-1][3]=='I'&&area[0][m-2][1]=='O'||area[0][m-1][3]=='O'&&area[0][m-2][1]=='I')
				&&(area[0][m-1][2]=='I'&&area[1][m-1][0]=='O'||area[0][m-1][2]=='O'&&area[1][m-1][0]=='I')
				&&(area[n-1][m-1][0]=='I'&&area[n-2][m-1][2]=='O'||area[n-1][m-1][0]=='O'&&area[n-2][m-1][2]=='I')
				&&(area[n-1][m-1][3]=='I'&&area[n-1][m-2][1]=='O'||area[n-1][m-1][3]=='O'&&area[n-1][m-2][1]=='I')
				&&(area[n-1][0][1]=='I'&&area[n-1][1][3]=='O'||area[n-1][0][1]=='O'&&area[n-1][1][3]=='I')
				&&(area[n-1][0][0]=='I'&&area[n-2][0][2]=='O'||area[n-1][0][0]=='O'&&area[n-2][0][2]=='I'))
				ok=1;
			return ;
	}
	int i,j,errors=0;
	char error[(N-2)*(N-2)][5];
	if(visit[x][y])
	{
		dfs(nextx(x,y),nexty(y));
		if(ok==1)
			return ;
	}
	else if(x==0)
	{
		for(i=0;i<m-2;i++)
		{
			if(!vis[1][i])
			{
				for(j=0;j<errors;j++)
				{
					if(strcmp(error[j],border[0][i])==0)
						goto next1;
				}
				if(judge(x,y,border[0][i]))
				{
					vis[1][i]=1;
					visit[x][y]=1;
					strcpy(area[x][y],border[0][i]);
					dfs(nextx(x,y),nexty(y));
					if(ok==1)
						return ;
					strcpy(error[errors++],border[0][i]);
					vis[1][i]=0;
					visit[x][y]=0;
				}
			}	
next1:;
		}
	}
	else if(y==m-1)
	{
		for(i=0;i<n-2;i++)
		{
			if(!vis[2][i])
			{
				for(j=0;j<errors;j++)
				{
					if(strcmp(error[j],border[1][i])==0)
						goto next2;
				}
				if(judge(x,y,border[1][i]))
				{
					vis[2][i]=1;
					strcpy(area[x][y],border[1][i]);
					visit[x][y]=1;
					dfs(nextx(x,y),nexty(y));
					if(ok==1)
						return ;
					strcpy(error[errors++],border[1][i]);
					vis[2][i]=0;
					visit[x][y]=0;
				}
			}
next2:;
		}
	}
	else if(x==n-1)
	{
		for(i=0;i<m-2;i++)
		{
			if(!vis[3][i])
			{
				for(j=0;j<errors;j++)
				{
					if(strcmp(error[j],border[2][i])==0)
						goto next3;
				}
				if(judge(x,y,border[2][i]))
				{
					vis[3][i]=1;
					strcpy(area[x][y],border[2][i]);
					visit[x][y]=1;
					dfs(nextx(x,y),nexty(y));
					if(ok==1)
						return ;
					strcpy(error[errors++],border[2][i]);
					vis[3][i]=0;
					visit[x][y]=0;
				}
			}		
next3:;
		}
	}
	else if(y==0)
	{
		for(i=0;i<n-2;i++)
		{
			if(!vis[4][i])
			{
				for(j=0;j<errors;j++)
				{
					if(strcmp(error[j],border[3][i])==0)
						goto next4;
				}
				if(judge(x,y,border[3][i]))
				{
					vis[4][i]=1;
					strcpy(area[x][y],border[3][i]);
					visit[x][y]=1;
					dfs(nextx(x,y),nexty(y));
					if(ok==1)
						return ;
					strcpy(error[errors++],border[3][i]);
					vis[4][i]=0;
					visit[x][y]=0;
				}
			}		
			next4:;
		}
	}
	else
	{
		for(i=0;i<(m-1)*(n-1);i++)
		{
			if(!vis[0][i])
			{
				for(j=0;j<errors;j++)
				{
					if(strcmp(error[j],center[i])==0)
						goto next5;
				}
				if(judge(x,y,center[i]))
				{
					vis[0][i]=1;
					strcpy(area[x][y],center[i]);
					visit[x][y]=1;
					dfs(nextx(x,y),nexty(y));
					if(ok==1)
						return ;
					strcpy(error[errors++],center[i]);
					vis[0][i]=0;
					visit[x][y]=0;
				}
			}
next5:;
		}
	}
}

int main()
{
	int i,j,help,inputs,oo[4],ii[4],flat;
	char s[5];
	while(scanf("%d%d%*c",&n,&m)&&n+m)
	{
		//getchar();
		corners1=corners2=corners3=corners4=borders1=borders2=borders3=borders4=centers=0;
		inputs=0;
		ok=flat=0;
		memset(oo,0,16);
		memset(ii,0,16);
		memset(vis,0,40*(N-2)*(N-2));
		memset(visit,0,2*(N)*(N)*4);
		for(i=0;i<n*m;i++)
		{
			help=0;
			scanf("%s",s);
			for(j=0;j<4;j++)
			{
				if(s[j]=='F')
				{
					help++;
					flat++;
				}
				if(s[j]=='O')
					oo[j]++;
				if(s[j]=='I')
					ii[j]++;
			}
			if(m==1&&n==1)
			{
				if(help==4)
					printf("YES\n");
				else
					printf("NO\n");
				goto next;
			}
			if(n==1)
			{
				strcpy(input[inputs++],s);
			}
			else if(m==1)
			{
				strcpy(input[inputs++],s);
			}
			else
			{
				if(help>=3)
				{
					printf("NO\n");
					goto next;
				}
				if(s[0]=='F'&&s[3]=='F')
				{
					strcpy(corner[0],s);
					corners1++;
				}
				else if(s[0]=='F'&&s[1]=='F')
				{
					strcpy(corner[1],s);
					corners2++;
				}
				else if(s[2]=='F'&&s[1]=='F')
				{
					strcpy(corner[2],s);
					corners3++;
				}
				else if(s[2]=='F'&&s[3]=='F')
				{
					strcpy(corner[3],s);
					corners4++;
				}
				else if(s[0]=='F')
				{
					strcpy(border[0][borders1++],s);
				}
				else if(s[1]=='F')
				{
					strcpy(border[1][borders2++],s);
				}
				else if(s[2]=='F')
				{
					strcpy(border[2][borders3++],s);
				}
				else if(s[3]=='F')
				{
					strcpy(border[3][borders4++],s);
				}
				else
				strcpy(center[centers++],s);
			}
		}
		if(n==1)
		{
			if(judge1()&&flat==2*(m+n))
				printf("YES\n");
			else
				printf("NO\n");
		}
		else if(m==1)
		{
			if(judge2()&&flat==2*(m+n))
				printf("YES\n");
			else
				printf("NO\n");
		}
		else
		{
			if(ii[0]!=oo[2]||ii[1]!=oo[3]||ii[2]!=oo[0]||ii[3]!=oo[1]||flat!=2*(m+n))
			{
				printf("NO\n");
				goto next;
			}
			if(corners1!=1||corners2!=1||corners3!=1||corners4!=1||borders1!=m-2||borders2!=n-2||borders3!=m-2||borders4!=n-2||centers!=(m-2)*(n-2))
			{
				printf("NO\n");
				goto next;
			}
				strcpy(area[0][0],corner[0]);
				visit[0][0]=1;

				strcpy(area[0][m-1],corner[1]);
				visit[0][m-1]=1;
				strcpy(area[n-1][m-1],corner[2]);
				visit[n-1][m-1]=1;
				strcpy(area[n-1][0],corner[3]);
				visit[n-1][0]=1;
			dfs(0,0);
			/*printf("%d ",corners1);
						printf("%d ",corners2);			printf("%d ",corners3);			printf("%d ",corners4);
						printf("%d ",borders1);
						printf("%d ",borders2);			printf("%d ",borders3);			printf("%d ",borders4);
			printf("\n%d ",centers);*/
			if(ok==1)
				printf("YES\n");
			else
				printf("NO\n");
		}
next:;
	 //gets(s);
	}
	return 0;
}



版本2:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define SIZE 8
using namespace std;

int n,m,ok;
char s[SIZE*SIZE][10],vis[SIZE*SIZE],area[SIZE][SIZE];

int cmp(const void *p,const void *q)
{
    /*if(strcmp((char *)p,(char *)q)!=0)
        return 1;
    else
        return 0;*/
        return strcmp((char *)p,(char *)q);//写错一次
}

int nextx(int x,int y)
{
    if(y==m-1)
        return x+1;
    else
        return x;
}

int nexty(int y)
{
    if(y==m-1)
        return 0;
    else
        return y+1;
}

int judge(int x,int y,int index)
{
    if((x==0&&s[index][0]!='F')||(x==n-1&&s[index][2]!='F')||(y==0&&s[index][3]!='F')||(y==m-1&&s[index][1]!='F'))
    return 0;
    int i,j,xx,yy,vector1[4][2]={{-1,0},{0,1},{1,0},{0,-1},},vector2[4][2]={{2,0},{3,1},{0,2},{1,3},};
    for(i=0;i<4;i++)
    {
        xx=x+vector1[i][0],yy=y+vector1[i][1];
        if(xx>=0&&xx<n&&yy>=0&&yy<m)//存在少许冗余
        {
            if(area[xx][yy]!=-1)//area写错一次
            {
                if(!((s[area[xx][yy]][vector2[i][0]]=='I'&&s[index][vector2[i][1]]=='O')||(s[area[xx][yy]][vector2[i][0]]=='O'&&s[index][vector2[i][1]]=='I'))||(s[index][vector2[i][1]]=='F'))
                    return 0;
            }
            else//少写一次
            {
                if(s[index][vector2[i][1]]=='F')
                    return 0;
            }
        }
    }
    return 1;
}

void dfs(int x,int y)
{
    if(ok==true)
        return ;
    if(x==n&&y==0)
    {
        ok=true;
        return ;
    }
    int i,j;
    char help[10]="a";
    for(i=0;i<m*n;i++)
    {
        if(!vis[i]&&strcmp(help,s[i])!=0&&judge(x,y,i))
        {
            vis[i]=1;
            area[x][y]=i;
            strcpy(help,s[i]);//tricks
            dfs(nextx(x,y),nexty(y));
            if(ok==true)
                return ;
            vis[i]=0;
            area[x][y]=-1;
        }
    }
}

int main()
{
    int i,j;
    int ff[4],ii[4],oo[4];
    while(scanf("%d%d",&n,&m)&&m+n)
    {
        memset(ff,0,16);
        memset(ii,0,16);
        memset(oo,0,16);
        memset(vis,0,SIZE*SIZE);
        memset(area,-1,SIZE*SIZE);
        ok=false;
        for(i=0;i<m*n;i++)
        {
            scanf("%s",s[i]);
            for(j=0;j<4;j++)
            {
                if(s[i][j]=='F')
                    ff[j]++;
                else if(s[i][j]=='I')
                    ii[j]++;
                else if(s[i][j]=='O')
                    oo[j]++;
            }
        }
        if(ff[0]!=m||ff[1]!=n||ff[0]!=ff[2]||ff[1]!=ff[3]||ii[0]!=oo[2]||ii[1]!=oo[3]||ii[2]!=oo[0]||ii[3]!=oo[1])
        {
            printf("NO\n");
            goto next;
        }
        //printf("%d %d",m,n);
        qsort(s,m*n,sizeof(s[0]),cmp);
       // puts("");
        //for(i=0;i<m*n;i++)
         //   puts(s[i]);
        dfs(0,0);
        if(ok==1)
            printf("YES\n");
        else
            printf("NO\n");
        next:;
    }

    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值