【DFS】hdu 2780 Su-Su-Sudoku

本文探讨了一个利用回溯搜索算法解决特定矩阵问题的方法。通过详细分析输入矩阵的约束条件,实现了一种有效的求解策略。该算法不仅处理了矩阵中元素的排列问题,还特别注意到了矩阵内部的行、列以及小矩阵内的元素限制,确保了最终解决方案的正确性和有效性。

http://acm.hdu.edu.cn/showproblem.php?pid=2780

分析:我去,注意可能输入的矩阵就不符合要求,以及最后一行不用再多输出空格了(各种处理,真的好讨厌)

回溯搜索

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int NM=9;
int vis[10],v1[10],v2[10],v3[10],k,flag,k1,k2;
char str[10][10];
struct Sudu{
	int x,y;
}s[100];

bool judge(int x,char num)
{
	int t1,t2,i,j;
	memset(vis,0,sizeof(vis));
	t1=s[x].x,t2=s[x].y;
	for(i=0;i<NM;i++)  //行
	{
		if(str[t1][i]==num)
			return 0;
	}
	for(i=0;i<NM;i++)  //列
	{		
		if(str[i][t2]==num)
		return 0;
	}
	t1=3*(s[x].x/3),t2=3*(s[x].y/3);
	for(i=t1;i<t1+3;i++)    //小矩阵
	{
		for(j=t2;j<t2+3;j++)
		{
			if(str[i][j]==num)
				return 0;
		}
	}
	return 1;
}

void DFS(int x)
{
	int i,j;
	if(x==k) 
	{
		flag=1;
		for(i=0;i<NM;i++)
		{
			for(j=0;j<NM;j++)
				printf("%c",str[i][j]);
			printf("\n");
		}
	}	
	if(flag) return;
	
	for(i=1;i<=NM;i++)  //
	{
		char num=i+'0';
		if(judge(x,num))
		{
			str[s[x].x][s[x].y]=i+'0';
			DFS(x+1);
			str[s[x].x][s[x].y]='0';
		}
	}
}

void check()
{
	int i,j,t1,t2,t;
	for(i=0;i<NM;i++)
	{
		memset(v1,0,sizeof(v1));
		memset(v2,0,sizeof(v2));
		for(j=0;j<NM;j++)
		{
			t1=str[i][j]-'0';
			t2=str[j][i]-'0';
			if(t1==0) continue;  //行
			if(!v1[t1])
				v1[t1]=1;
			else
			{flag=1;return;}
			
			if(t2==0) continue;  //列
			if(!v2[t2])
				v2[t2]=1;
			else
			{flag=1;return;}
		}
	}
	
	for(i=0;i<NM;i+=3)
		for(j=0;j<NM;j+=3)
		{
			memset(v3,0,sizeof(v3));
			for(k1=i;k1<i+3;k1++)
				for(k2=j;k2<j+3;k2++)
				{
					t=str[k1][k2]-'0';
					if(t==0) continue;
					if(!v3[t]) v3[t]=1;
					else
					{flag=1;return;}
				}
		}
		
}

int main()
{
	int i,j,T;
	scanf("%d",&T);
	while(T--)
	{
		k=1;
		for(i=0;i<NM;i++)
		{
			scanf("%s",str[i]);
			for(j=0;j<NM;j++)
			{
				if(str[i][j]=='0')
				{
					s[k].x=i,s[k].y=j;
					k++;
				}
			}
		}
		flag=0;
		check();  //判断输入是否符合要求
		if(flag)
		{
			printf("Could not complete this grid.\n");
			if(T) printf("\n");
			continue;
		}
		flag=0;
		DFS(1);
		if(!flag)
			printf("Could not complete this grid.\n");
		if(T) printf("\n");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值