• 【洛谷P4205】智慧珠游戏【dfs】


    题目大意:

    题目链接:https://www.luogu.org/problem/P4205

    智慧珠游戏拼盘由一个三角形盘件和 12 个形态各异的零件组成。拼盘的盘 件如图 1 所示
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    可以放到盘件的任一位置,条件是能有地方放,且 尺寸合适,所有的零件都允许旋转(0º、90º、180º、270º)和翻转(水平、竖直)。

    现给出一个盘件的初始布局,求一种可行的智慧珠摆放方案,使所有的零件 都能放进盘件中。


    思路:

    把每一块智慧珠的所有摆放方式打出来,然后暴搜依次确定位置。
    还有什么好说的吗
    注意不用手动把所有的情况打出来,只要打出其中一个,让程序自己将这个图形旋转、翻转然后打印进去。注意一个图形是否翻转,以及每次旋转的角度是要打进去的。这样可以将1000+1000+行的暴搜压缩成200200行。
    先把难填的图形填进去,方便剪枝。
    剪枝就是每到一个局面就泳并查集判断每一个没放智慧珠的空联通快的大小,如果小于3,或者大小是6,就直接返回即可。
    最后卡一个搜索次数,达到就直接退了。
    时间复杂度O(O(玄学))


    代码:

    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #include <ctime>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    int tot,flag,pos[13][10][10][3],map[4][4],cpy[4][4],cnt[13],sum[13],vis[15][15],father[200],size[200];
    bool used[13];
    double T;
    char ch;
    
    const int Map[13][4][4]=
    {
    	{{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
    	{{1,1,0,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}},
    	{{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
    	{{1,1,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}},
    	{{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
    	{{1,0,0,0},{1,0,0,0},{1,1,1,0},{0,0,0,0}},
    	{{1,1,1,1},{0,1,0,0},{0,0,0,0},{0,0,0,0}},
    	{{1,1,1,0},{1,0,1,0},{0,0,0,0},{0,0,0,0}},
    	{{1,1,1,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}},
    	{{1,1,1,0},{0,0,1,1},{0,0,0,0},{0,0,0,0}},
    	{{0,1,0,0},{1,1,1,0},{0,1,0,0},{0,0,0,0}},
    	{{1,0,0,0},{1,1,0,0},{0,1,1,0},{0,0,0,0}},
    	{{1,1,1,1},{1,0,0,0},{0,0,0,0},{0,0,0,0}}
    };
    
    const int Swap[13]={0,0,0,1,0,0,1,0,1,1,0,0,1};
    const int Rotate[13]={0,15,3,15,1,15,15,15,15,15,1,15,15};
    const int dx[]={0,0,0,-1,1},dy[]={0,-1,1,0,0};
    const int next[]={0,2,4,1,-1,3,12,6,5,11,9,7,8};
    
    inline void add(int S)
    {
    	for (register int k=1;k<=4;k++)
    	{
    		for (register int i=0;i<4;i++)
    			for (register int j=0;j<4;j++)
    				cpy[i][j]=map[3-j][i];
    		memcpy(map,cpy,sizeof(map));
    		if (Rotate[S]&(1<<k-1))
    		{
    			int px=-1,py,q=0;
    			cnt[S]++;
    			for (register int i=0;i<4;i++)
    				for (register int j=0;j<4;j++)
    					if (map[i][j])
    					{
    						if (px<0) px=i,py=j;
    						else
    						{
    							q++;
    							pos[S][cnt[S]][q][1]=i-px;
    							pos[S][cnt[S]][q][2]=j-py;
    						}
    					}
    		}
    	}
    	if (!Swap[S]) return;
    	for (register int i=0;i<4;i++)
    		for (register int j=0;j<2;j++)
    			swap(map[i][j],map[i][3-j]);
    	for (register int k=1;k<=4;k++)
    	{
    		for (register int i=0;i<4;i++)
    			for (register int j=0;j<4;j++)
    				cpy[i][j]=map[3-j][i];
    		memcpy(map,cpy,sizeof(map));
    		if (Rotate[S]&(1<<k-1))
    		{
    			int px=-1,py,q=0;
    			cnt[S]++;
    			for (register int i=0;i<4;i++)
    				for (register int j=0;j<4;j++)
    					if (map[i][j])
    					{
    						if (px<0) px=i,py=j;
    						else
    						{
    							q++;
    							pos[S][cnt[S]][q][1]=i-px;
    							pos[S][cnt[S]][q][2]=j-py;
    						}
    					}
    		}
    	}
    }
    
    inline void prepare()
    {
    	for (register int i=1;i<=12;i++)
    	{
    		memcpy(map,Map[i],sizeof(map));
    		for (register int j=0;j<4;j++)
    			for (register int k=0;k<4;k++)
    				sum[i]+=Map[i][j][k];
    		add(i);
    	}
    }
    
    inline bool check(int x,int y,int S,int k)
    {
    	for (register int i=1;i<=sum[S];i++)
    	{
    		int xx=x+pos[S][k][i][1],yy=y+pos[S][k][i][2];
    		if (vis[xx][yy] || xx>10 || yy>xx || xx<1 || yy<1) return 0;
    	}
    	return 1;
    }
    
    inline int find(int x)
    {
    	return x==father[x]?x:father[x]=find(father[x]);
    }
    
    inline int com(int x,int y)
    {
    	return (x-1)*10+y;
    }
    
    inline void dfs(int x)
    {
    	if (x==-1)
    	{
    		flag=1;
    		return;
    	}
    	tot++;
    	for (register int i=1;i<=10;i++)
    		for (register int j=1;j<=i;j++)
    		{
    			father[com(i,j)]=com(i,j);
    			size[com(i,j)]=1;
    		}
    	for (register int i=1;i<=10;i++)
    		for (register int j=1;j<=i;j++)
    			if (!vis[i][j])
    				for (register int k=1;k<=4;k++)
    				{
    					int xx=i+dx[k],yy=j+dy[k];
    					if (!vis[xx][yy])
    					{
    						if (xx<1 || xx>10 || yy<1 || yy>xx) continue;
    						int p=find(com(i,j)),q=find(com(xx,yy));
    						if (p==q) continue;
    						size[p]+=size[q]; father[q]=p;
    					}
    				}
    	for (register int i=1;i<=10;i++)
    		for (register int j=1;j<=i;j++)
    			if (!vis[i][j] && size[find(com(i,j))]<3 || size[find(com(i,j))]==6)
    				return;
    	if (used[x])
    	{
    		dfs(next[x]);
    		return;
    	}
    	for (register int i=1;i<=10;i++)
    		for (register int j=1;j<=i;j++)
    			for (int k=1;k<=cnt[x];k++)
    				if (check(i,j,x,k))
    				{
    					for (register int l=1;l<=sum[x];l++)
    						vis[i+pos[x][k][l][1]][j+pos[x][k][l][2]]=x;
    					dfs(next[x]);
    					if (tot>=800000) return;
    					if (flag) return;
    					for (register int l=1;l<=sum[x];l++)
    						vis[i+pos[x][k][l][1]][j+pos[x][k][l][2]]=0;
    				}
    }
    
    int main()
    {
    	prepare();
    	for (register int i=1;i<=10;i++)
    		for (register int j=1;j<=i;j++)
    		{
    			while (ch=getchar()) if (ch=='.' || (ch>='A' && ch<='Z')) break;
    			if (ch!='.')
    			{
    				used[ch-'A'+1]=1;
    				vis[i][j]=ch-'A'+1;
    			}
    		}
    	dfs(10);
    	if (flag==1)
    		for (register int i=1;i<=10;i++,putchar(10))
    			for (register int j=1;j<=i;j++)
    				printf("%c",vis[i][j]+'A'-1);
    	else printf("No solution
    ");
    	return 0;
    }
    
  • 相关阅读:
    熟悉常用的Linux操作
    Python基础综合练习
    简易c语言文法
    词法分析程序
    组合数据类型综合练习
    综合练习:词频统计
    词法分析程序2
    我对编译原理的理解
    【分享】博客美化(6)为你的博文自动添加目录
    python爬虫的基本思路
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998015.html
Copyright © 2020-2023  润新知