关于UVA,TLE求助
  • 板块学术版
  • 楼主DGFLSzfd
  • 当前回复4
  • 已保存回复4
  • 发布时间2024/8/27 20:14
  • 上次更新2024/8/27 21:28:57
查看原帖
关于UVA,TLE求助
981551
DGFLSzfd楼主2024/8/27 20:14

这篇帖子有两个问题

关于UVA

有没有什么别的UVA的镜像网站,vjudge也太慢了,交一次要等一分钟两分钟,我这个急性子真的受不了!还是说所有的镜像网站都一样。

超时求条

题目:sudoku(数独)

我把代码交在spoj一样的题目上过了,UVA一直超时,求大佬调试。(蒟蒻第一次挑战黑题,代码可能和题解相似,但我理解了,并非复制粘贴抄袭)

#include<bits/stdc++.h>
using namespace std;

const int N=1<<16,M=19;

char s[M][M];
int num[N],cnt[N],fe[M][M];
//cnt 一个数换成二进制,里面有多少个1
//num 这个数是2的几次方

inline void update(int x,int y,int z)   //让所有相关的位置不能为z
{
	for(int i=1; i<=16; i++)
	{
		fe[x][i]&=~(1<<z);
		fe[i][y]&=~(1<<z);
	}
	int stx=(x-1)/4*4+1,sty=(y-1)/4*4+1;//16宫格左上角
	for(int i=stx; i<stx+4; i++)
	{
		for(int j=sty; j<sty+4; j++)
			fe[i][j]&=~(1<<z);
	}

}

bool dfs(int left)
{
//	cout<<left<<endl;
	if(!left)
	{
		for(int i=1; i<=16; i++) printf("%s\n",s[i]+1);
		return 1;
	}

	int fe_save[M][M];
	memcpy(fe_save,fe,sizeof(fe_save));

	int mn=17,nx,ny;
	for(int i=1; i<=16; i++)   //只有一个能填的填了
	{
		for(int j=1; j<=16; j++)
		{
			if(s[i][j]!='-') continue;
			if(!fe[i][j]) return 0;
			if(cnt[fe[i][j]]==1)
			{
				s[i][j]=num[fe[i][j]]+'A';
				update(i,j,num[fe[i][j]]);

				if(dfs(left-1)) return 1;
				s[i][j]='-';
				memcpy(fe,fe_save,sizeof(fe_save));
				return 0;
			}
			if(cnt[fe[i][j]]<mn)
			{
				mn=cnt[fe[i][j]];
				nx=i;
				ny=j;
			}
		}
	}

	for(int i=1; i<=16; i++)   //某个字母不能填在某一行的任何位置则回溯;只能填在一个位置则向下搜索。
	{
		int vis=0,now_left=0;
		for(int j=1; j<=16; j++)   //第i行有几个空,哪些数字已经被填了
		{
			if(s[i][j]=='-') now_left++;
			else vis|=1<<(s[i][j]-'A');
		}
		if(!now_left) continue;
		for(int j=0; j<16; j++)
		{
			if(vis>>j&1) continue;
			int cntt=0,last;
			for(int k=1; k<=16; k++)
			{
				if(s[i][k]!='-') continue;
				if(!(fe[i][k]>>j&1)) continue;
				cntt++;
				last=k;
				if(cntt>=2) break;
			}
			if(!cntt) return 0;
			if(cntt==1)
			{
				s[i][last]=j+'A';
				update(i,last,j);
				if(dfs(left-1))return 1;
				s[i][last]='-';
				memcpy(fe,fe_save,sizeof(fe_save));
				return 0;
			}
		}
	}

	for(int i=1; i<=16; i++)   //某个字母不能填在某一列的任何位置则回溯;只能填在一个位置则向下搜索。
	{
		int vis=0,now_left=0;
		for(int j=1; j<=16; j++)   //第i行有几个空,哪些数字已经被填了
		{
			if(s[j][i]=='-') now_left++;
			else vis|=1<<(s[j][i]-'A');
		}
		if(!now_left) continue;
		for(int j=0; j<16; j++)
		{
			if(vis>>j&1) continue;
			int cntt=0,last;
			for(int k=1; k<=16; k++)
			{
				if(s[k][i]!='-') continue;
				if(!(fe[k][i]>>j&1)) continue;
				cntt++;
				last=k;
				if(cntt>=2) break;
			}
			if(!cntt) return 0;
			if(cntt==1)
			{
				s[last][i]=j+'A';
				update(last,i,j);
				if(dfs(left-1))return 1;
				s[last][i]='-';
				memcpy(fe,fe_save,sizeof(fe_save));
				return 0;
			}
		}
	}
	for (int x=1; x<=13; x+=4)   //16宫格,枚举起点 (x,y)
	{
		for (int y=1; y<=13; y+=4)
		{
			int vis=0,now_left=0;
			for (int i=x; i<x+4; i++)   //遍历所有点
			{
				for (int j=y; j<y+4; j++)
				{
					if (s[i][j]=='-') now_left++;
					else vis|=1<<(s[i][j]-'A'); //已填
				}
			}
			if (!now_left) continue; //填满
			for (int k=0; k<16; k++)   //枚举字母
			{
				if (vis>>k&1) continue;
				int cntt=0,lastx,lasty;
				for (int i=x; i<x+4; i++)
				{
					for (int j=y; j<y+4; j++)
					{
						if (s[i][j]!='-') continue;
						if (!(fe[i][j]>>k&1)) continue;
						cntt++;
						lastx=i;
						lasty=j;
					}
				}
				if (!cntt) return 0;
				if (cntt==1)
				{
					s[lastx][lasty]=k+'A';
					update(lastx,lasty,k);
					if (dfs(left-1)) return 1;
					s[lastx][lasty]='-';
					memcpy(fe,fe_save,sizeof(fe_save));
					return 0;
				}
			}
		}
	}
	for (int i=fe[nx][ny]; i; i-=i&-i)   //对可填字母最少的点进行枚举搜索
	{
		int z=num[i&-i];
		s[nx][ny]=z+'A';
		update(nx,ny,z);
		if (dfs(left-1)) return 1;
		s[nx][ny]='-';
		memcpy(fe,fe_save,sizeof(fe));
	}
	return 0;
}

int T=0;
int main()
{
	for(int i=0; i<16; i++) num[1<<i]=i;
	for(int i=0; i<N; i++)
	{
		for(int j=i; j; j-=j&-j)
			cnt[i]++;
	}
	
	//cin>>T;
	while(scanf("%s",s[1]+1))
	{
		if(T) puts("");
		T=1;
		
		for(int i=2; i<=16; i++)
			scanf("%s",s[i]+1);
		for(int i=1; i<=16; i++)
		{
			for(int j=1; j<=16; j++)
				fe[i][j]=N-1;
		}
		int left=0;
		for(int i=1; i<=16; i++)
		{
			for(int j=1; j<=16; j++)
			{
				if(s[i][j]=='-') left++;
				else update(i,j,s[i][j]-'A');
			}
		}
		dfs(left);
	}

}

2024/8/27 20:14
加载中...