puzzle(1031)数壹、数和

目录

数壹

5*5

 10*10

 策略

数和

6*6

10*10

SGU - 454 Kakuro


数壹

在线play

涂黑部分格子,同时满足以下规则:
- 每行及每列中,同一个数字不能出现1次以上。
- 涂黑的格子不能水平相邻或垂直相邻。
- 所有未涂黑的格子应该连成一个整体。

5*5

  

  

 10*10

 策略

从边界开始,先推出一个确定涂黑的格子,然后它的邻居一定是不涂黑的,以此类推。

数和

在线play

1. 方格内需填入1-9中的一个数
2. 黑色方格内的数提示了与其相邻(右方或下方)的连续白色方格中数的总和。
3. 连续白色方格中的数不得重复。

6*6

10*10

 

SGU - 454 Kakuro


Kakuro puzzle is played on a nm grid of "black" and "white" cells. Apart from the top row and leftmost column which are entirely black, the grid has some amount of white cells which form "runs" and some amount of black cells. "Run" is a vertical or horizontal maximal one-lined block of adjacent white cells. Each row and column of the puzzle can contain more than one "run". Every white cell belongs to exactly two runs — one horizontal and one vertical run. Each horizontal "run" always has a number in the black half-cell to its immediate left, and each vertical "run" always has a number in the black half-cell immediately above it. These numbers are located in "black" cells and are called "clues".
The rules of the puzzle are simple:

  • place a single digit from 1 to 9 in each "white" cell
  • each digit may only be used once in each "run"
  • for all runs, the sum of all digits in a "run" must match the clue associated with the "run"


Given the grid, your task is to find a solution for the puzzle.


Picture of the first sample input


Picture of the first sample output

Input

The first line of input contains two integers n and m (2 ≤ n,m ≤ 6) — the number of rows and columns correspondingly. Each of the next n lines contains descriptions of m cells. Each cell description is one of the following 5-character strings:

  • .....
     — "white" cell;
  • XXXXX
     — "black" cell with no clues;
  • AA\BB
     — "black" cell with one or two clues. 
    AA
     is either a 2-digit clue for the corresponding vertical run, or 
    XX
     if there is no associated vertical run. 
    BB
     is either a 2-digit clue for the corresponding horizontal run, or 
    XX
     if there is no associated horizontal run.

The first row and the first column of the grid will never have any white cells. The given grid will have at least one "white" cell.
It is guaranteed that the given puzzle has at least one solution.

Output

Print n lines to the output with m cells in each line. For every "black" cell print '

' (underscore), for every "white" cell print the corresponding digit from the solution. Delimit cells with a single space, so that each row consists of 2m-1 characters.
If there are many solutions, you may output any of them.

Sample 1

InputcopyOutputcopy
6 6
XXXXX XXXXX 28\XX 17\XX 28\XX XXXXX
XXXXX 22\22 ..... ..... ..... 10\XX
XX\34 ..... ..... ..... ..... .....
XX\14 ..... ..... 16\13 ..... .....
XX\22 ..... ..... ..... ..... XXXXX
XXXXX XX\16 ..... ..... XXXXX XXXXX
_ _ _ _ _ _
_ _ 5 8 9 _
_ 7 6 9 8 4
_ 6 8 _ 7 6
_ 9 2 7 4 _
_ _ 7 9 _ _

Sample 2

InputcopyOutputcopy
3 3
XXXXX 04\XX XXXXX
XX\04 ..... XXXXX
XXXXX XXXXX XXXXX
_ _ _
_ 4 _
_ _ _

#include<iostream>
#include<string>
using namespace std;

int n, m;
int col[6][6], row[6][6], ans[6][6];
int numr[6][6], numc[6][6];
bool pre[6][36][10];//pre[i][j][k]表示是否存在包含k的i个不同的数使得和为j
int flag[6][6][10];//flag[i][j][k]=2才表示根据pre算出来(i,j)处是否可能是k

void getpre()//初始化pre
{
	int s;
	for (int i = 1; i < 6; i++)for (int j = 1; j < 36; j++)
		for (int k = 1; k < 10; k++)pre[i][j][k] = false;
	for (int x1 = 1; x1 < 10; x1++)
	{
		pre[1][x1][x1] = true;
		for (int x2 = x1 + 1; x2 < 10; x2++)
		{
			pre[2][x1 + x2][x1] = pre[2][x1 + x2][x2] = true;
			for (int x3 = x2 + 1; x3 < 10; x3++)
			{
				s = x1 + x2 + x3;
				pre[3][s][x1] = pre[3][s][x2] = pre[3][s][x3] = true;
				for (int x4 = x3 + 1; x4 < 10; x4++)
				{
					pre[4][s + x4][x1] = pre[4][s + x4][x2] = true;
					pre[4][s + x4][x3] = pre[4][s + x4][x4] = true;
					for (int x5 = x4 + 1; x5 < 10; x5++)
					{
						pre[5][s + x4 + x5][x1] = true;
						pre[5][s + x4 + x5][x2] = pre[5][s + x4 + x5][x3] = true;
						pre[5][s + x4 + x5][x4] = pre[5][s + x4 + x5][x5] = true;
					}
				}
			}
		}
	}
}

void getflag()//初始化flag和numr和numc
{
	for (int i = 1; i < n; i++)for (int j = 1; j < m; j++)
		for (int k = 1; k < 10; k++)flag[i][j][k] = 0;
	int l;
	for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)
	{
		if (row[i][j] > 0)
		{
			l = 0;
			while (row[i][j + l + 1] < 0)l++;
			numr[i][j] = l;
			for (int n = 1; n < 10; n++)if (pre[l][row[i][j]][n])
				for (int k = 1; k <= l; k++)flag[i][j + k][n]++;
		}
		if (col[i][j] > 0)
		{
			l = 0;
			while (col[i + l + 1][j] < 0)l++;
			numc[i][j] = l;
			for (int n = 1; n < 10; n++)if (pre[l][col[i][j]][n])
				for (int k = 1; k <= l; k++)flag[i + k][j][n]++;
		}
	}
}

int num(char a, char b)
{
	if (a == 'X')return 0;
	if (a == '.')return -1;
	return (a - '0') * 10 + b - '0';
}

bool ok(int r, int c, int k)
{
	int i, j, s = k, l=-1;
	for (j = c - 1; ans[r][j] > 0; j--)
	{
		if (ans[r][j] == k)return false;
		s += ans[r][j], l--;
	}
	l += numr[r][j];
	if (s > row[r][j] - (l + 1)*l / 2)return false;
	if (s < row[r][j] - (19 - l)*l / 2)return false;
	//if (c == m - 1 || col[r][c + 1] >= 0)if (s != row[r][j])return false;
	s = k, l = -1;
	for (i = r - 1; ans[i][c] > 0; i--)
	{
		if (ans[i][c] == k)return false;
		s += ans[i][c], l--;
	}
	l += numc[i][c];
	if (s > col[i][c] - (l + 1)*l / 2)return false;
	if (s < col[i][c] - (19 - l)*l / 2)return false;
	//if (r == n - 1 || row[r + 1][c] >= 0)if (s != col[i][c])return false;
	return true;
}

bool trys(int r, int c)
{
	if (c == m)r++, c = 1;
	if (r == n)return true;
	if (col[r][c] >= 0)return trys(r, c + 1);
	if (r % 2)
	{
		for (int k = 1; k <= 9; k++)if (flag[r][c][k] == 2 && ok(r, c, k))
		{
			ans[r][c] = k;
			if (trys(r, c + 1))return true;
		}
	}
	else
	{
		for (int k = 9; k >= 1; k--)if (flag[r][c][k] == 2 && ok(r, c, k))
		{
			ans[r][c] = k;
			if (trys(r, c + 1))return true;
		}
	}
	return false;
}

int main()
{
	ios::sync_with_stdio(false);
	getpre();
	cin >> n >> m;
	string s;
	for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)
	{
		cin >> s;
		col[i][j] = num(s[0], s[1]);
		row[i][j] = num(s[3], s[4]);
		ans[i][j] = 0;
	}
	getflag();
	trys(1, 1);
	for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)
	{
		if (ans[i][j])cout << ans[i][j];
		else cout << '_';
		if (j < m - 1)cout << ' ';
		else cout << endl;
	}
	return 0;
}

没能AC,Time Limit Exceeded on test 218

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值