poj 3074 Sudoku

坑爹的数独呀!又是搜索,又是剪枝~~~

代码如下:

#include<iostream>
#include<stdio.h>
#include<string.h>
const int MAX_COLOUMN=81+9*9+9*9+9*9+2;
const int MAX_ROW=81*9+2;
int cnt[MAX_COLOUMN];
int most,coloumn;
bool ans[MAX_ROW];
struct Point
{
	int up,down,left,right;
	int coloumn;
	int row;
}node[MAX_ROW*MAX_COLOUMN+MAX_COLOUMN];

void init(int m)
{
	int i;
	for(i=0;i<m;i++)
	{
		node[i].down=i;
		node[i].up=i;
		node[i].coloumn=i;
		node[i].left=i-1;
		node[i].right=i+1;
		cnt[i]=0;
	}
	node[0].left=m;
	node[m].right=0;
}

void remove (int c)
{
	node[node[c].right].left=node[c].left;
	node[node[c].left].right=node[c].right;
	int t,tt;
	for(t=node[c].down;t!=c;t=node[t].down)
	{
		for(tt=node[t].right;tt!=t;tt=node[tt].right)
		{
			cnt[node[tt].coloumn]--;
			node[node[tt].down].up=node[tt].up;
			node[node[tt].up].down=node[tt].down;
		}
	}
}

void resume(int c)
{
	int t,tt;
	for(t=node[c].up;t!=c;t=node[t].up)
	{
		for(tt=node[t].left;tt!=t;tt=node[tt].left)
		{
			cnt[node[tt].coloumn]++;
			node[node[tt].up].down=tt;
			node[node[tt].down].up=tt;
		}
	}
	node[node[c].right].left=c;
	node[node[c].left].right=c;
}

bool dfs(int k)
{
	int i,j;
	if(k>=most) return false;
	if(node[coloumn].right==coloumn)
	{
		if(k<most)
			most=k;
		return true;
	}
	int t=coloumn+1;
	int c;
	for(i=node[coloumn].right;i!=coloumn;i=node[i].right)
	{
		if(cnt[i]<t)
		{
			c=i;t=cnt[i];
			if(t==1) break;
		}
	}
	remove(c);
	for(i=node[c].down;i!=c;i=node[i].down)
	{
		for(j=node[i].right;j!=i;j=node[j].right)
		{
			remove(node[j].coloumn);
		}
		ans[node[j].row]=true;
		if(dfs(k+1))
		{
			return true;
		}
		ans[node[j].row]=false;
		for(j=node[j].left;j!=i;j=node[j].left)
		{
			resume(node[j].coloumn);
		}
	}
	resume(c);
	return false;
}

bool graph[MAX_ROW][MAX_COLOUMN];
void addrow(int i,int j,int k)
{
	int curr=(i*9+j)*9+k;
	graph[curr][(i*9+j)]=true;
	graph[curr][81+i*9+k]=true;
	graph[curr][81+81+j*9+k]=true;
	int tr=i/3;
	int tc=j/3;
	graph[curr][81+81+81+(tr*3+tc)*9+k]=true;
}
char str[MAX_ROW];


int main()
{
	int N,M,i,j,k;
	while(scanf("%s",str)!=EOF)
	{
		if(strcmp(str,"end")==0) break;
		N=81*9;
		M=9*9+9*9+9*9+9*9;
		coloumn=M;
		int cur=coloumn+1;
		init(coloumn);
		memset(graph,0,sizeof(graph));
		for(i=0;i<9;i++)
			for(j=0;j<9;j++)
			{
				if(str[i*9+j]=='.')
				{
					for(k=0;k<9;k++)
					{
						addrow(i,j,k);
					}
					continue;
				}
				k=str[i*9+j]-'1';
				addrow(i,j,k);
			}
			for(i=0;i<N;i++)
			{
				int start=cur;
				int pre=cur;
				for(j=0;j<M;j++)
				{
					if(graph[i][j])
					{
						int pos=j;
						node[cur].up=node[pos].up;
						node[node[pos].up].down=cur;
						node[cur].down=pos;
						node[pos].up=cur;
						cnt[pos]++;
						node[cur].coloumn=pos;
						node[cur].left=pre;
						node[pre].right=cur;
						node[cur].right=start;
						node[start].left=cur;
						node[cur].row=i;
						pre=cur++;
					}
				}
			}
			most=N+1;
			memset(ans,false,sizeof(ans));
			dfs(0);
			for(i=0;i<81;i++)
				for(j=0;j<9;j++)
					if(ans[i*9+j])
					{
						printf("%d",j+1);
						break;
					}
					printf("\n");
	}
	return 0;
}

				





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值