求助,还可以怎么剪枝
查看原帖
求助,还可以怎么剪枝
263374
FanYongchen楼主2021/2/13 09:26
#include <iostream>
#include <cstring>
using namespace std;
const int N=16;
int mp[21][21]={0};
int row[21],col[21],matrix[21];
int ccnt[21]={0};
bool isok=false;
void printMap()
{
	cout<<"------------------------------\n";
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			if(mp[i][j]==-1) printf("-");
			else printf("%c",char(mp[i][j]+'A'));
		}
		cout<<"\n";		
	}
	cout<<"------------------------------\n";
}
int getCnt(int i,int j)
{
	int tot=0;
	for(int k=0;k<16;k++)
		if((row[i]>>k)&1||(col[j]>>k)&1||(matrix[i/4*4+j/4]>>k)&1) tot++;
	return tot;
}
void Put(int i,int j,int k)
{
	mp[i][j]=k;
	row[i]|=(1<<mp[i][j]),col[j]|=(1<<mp[i][j]),matrix[i/4*4+j/4]|=(1<<mp[i][j]);
}
void Take(int i,int j,int k)
{
	mp[i][j]=-1;
	row[i]&=(~(1<<k)),col[j]&=(~(1<<k)),matrix[i/4*4+j/4]&=(~(1<<k));
}
void dfs(int tot)
{
	printMap(); 
	if(tot>256) isok=true,printMap();	
	if(isok) return;
	int x=-1,y=-1,minn=0x7fffffff;
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
		{
			if(mp[i][j]!=-1) continue;
			int k=16-getCnt(i,j);
			if(k==1)//剪枝1,只能放一个 
			{
				for(int l=0;l<16;l++)
					if(!((row[i]>>l)&1||(col[j]>>l)&1||(matrix[i/4*4+j/4]>>l)&1))
					{
						ccnt[l]++;
						Put(i,j,l);
						dfs(tot+1);
						Take(i,j,l);
						ccnt[l]--;
						break;
					}
				return;
			}
			if(k==0) return;
			if(k<minn) minn=k,x=i,y=j;
		}	
	for(int c=0;c<16;c++)//剪枝2,有一个字母还要放的个数小于能放的格子数 
	{
		int t=0;
		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
				if(!((row[i]>>c)&1||((col[j]>>c)&1)||((matrix[i/4*4+j/4]>>c)&1))&&mp[i][j]==-1) t++;
		if(t<16-ccnt[c]) return;
	}
	
	for(int i=0;i<16;i++)
	{
		if(!((row[x]>>i)&1||(col[y]>>i)&1||(matrix[x/4*4+y/4]>>i)&1))
		{
			ccnt[i]++;
			Put(x,y,i);
			dfs(tot+1);
			Take(x,y,i);
			ccnt[i]--;
		}
	}
}
int main()
{
	memset(mp,-1,sizeof(mp));
	int cnt=0;
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
		{
			char c;
			cin>>c;
			if(c!='-') 
			{
				Put(i,j,c-'A');
				cnt++;
				ccnt[c-'A']++;
			}
		}
	dfs(cnt);
	return 0;
}

我看了一下别人的题解,但好像他们说的行、列、十六宫格剪枝我都在剪枝1中出现了。

2021/2/13 09:26
加载中...