POJ2044 天气预报---状态细则

墙角数枝梅,凌寒独自开。
遥知不是雪,为有暗香来。——王安石

题目:天气预报

网址:http://poj.org/problem?id=2044
你是一个可以控制降雨的神仙。
你是一个仁慈的神,希望土地在平时可以有足够的雨水,在赶集和过节能够充满阳光。
你负责掌控一个村子的天气状况。
这个村子呈4 x 4的网格状分布,村子内的每个区域被编号如下图所示:
image

你拥有一片2 x 2大小的云,这片云不能到村子以外的地方。

你将获得一段时间内村子每个区域的赶集和过节时间表。

在这段时间的第一天,中部地区(6-7-10-11)将会下雨。

在接下来的每一天中,您可以在四个基本方向(东南西北)之中选取一个方向,将云移动1或2个方格,或将其保持在相同位置。

不允许对角线移动。
任何地区都不能连续七天或以上时间都不降雨。

这段时间以外的日子的下雨状况你无需做任何考虑。

输入格式

输入包含多组测试用例。

对于每组测试用例,第一行包含一个整数N,表示这段时间的具体天数。

接下里N行,描绘了接下来N天的赶集和过节时间表,第i行表示第i天的时间表。

这N行里,每行包含16个数字(0或1),0表示正常的一天,1表示赶集和过节的一天,第i个数字表示第i个区域的具体情况。
每行数字之间用空格隔开。
当输入测试用例N=0时,表示输入终止,且该用例无需处理。

输出格式

每个测试用例输出一个整数0或1,如果可以保证整个时间段内,该下雨的地方下雨,不该下的地方不下,则输出1。
如果不能保证则输出0,每个结果占一行。

数据范围

1≤N≤365

输入样例:
1
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
7
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 1 0 0 0 0 1 1 0 0 1
0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1
0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0
0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0
7
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0
0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0
0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0
0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0
1 0 0 1 1 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0
0
输出样例:
0
1
0
1

这道题其实细节上颇多。

首先,判断每个地区是否连续七天没有浇水,实际上可以通过四个角来判断;

如果定义状态为该云目前的坐标,那么,当四个角中其中有不符题意的状态,难以表示;

如果该状态为坐标以及四个角的情况,那么,对于相同状态下,不同天数所处的情况也不同;

综上,定义:状态(time,(x,y),(d1,d2,d3,d4));

因此,对于这样一个状态,是满足唯一性,也就是说,可以保证该状态可以准确描述状态的情况;

连续七天,因此为了保险起见,我们使用八进制状态压缩(d1,d2,d3,d4),即d1 + d2 * 8 + d3 * 64 + d4 * 512;
其余,就注意细节即可;
代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
struct state
{
	int turn, pos, code;
	state (int x, int y, int z) : turn(x), pos(y), code(z) {}
};
const int dx[10] = {-1, 1, 0, 0, -2, 2, 0, 0}, dy[10] = {0, 0, -1, 1, 0, 0, -2, 2};
bool day[366][17], vis[366][17][4096];
int n;
bool valid(state p)
{	
	if(vis[p.turn][p.pos][p.code]) return false;
	for(int i = 0; i < 4; ++ i)
	{
		if(p.code % 8 >= 7) return false;
		p.code >>= 3;
	}
	if(day[p.turn][p.pos] || day[p.turn][p.pos + 1] || day[p.turn][p.pos + 4] || day[p.turn][p.pos + 5]) return false;
	return true;
}
bool valid(int x, int y)
{
	if(x < 0 || x > 2 || y < 0 || y > 2) return false;
	//be aware of it : The range is [0, 2] !! 
	return true;
}
bool bfs()
{
	queue <state> Q;
	int x, y;
	int p[4] = {}, tmp = 0;
	while(!Q.empty()) Q.pop();
	memset(vis, false, sizeof(vis));
	if(!valid(state(1, 6, 1 + 8 + 64 + 512))) return false;
	vis[1][6][1 + 8 + 64 + 512] = true;
	Q.push(state(1, 6, 1 + 8 + 64 + 512));
	// The coodinate must be transfered into this form (x,y) to avoid mistakes about position!!
	while(!Q.empty())
	{
		state now = Q.front(); Q.pop();
		tmp = now.code;
		for(int i = 0; i < 4; ++ i)
		{
			p[i] = tmp % 8;
			tmp >>= 3;
		}
		x = (now.pos - 1) / 4, y = (now.pos - 1) % 4;
		for(int i = 0; i < 9; ++ i)
		{
			state next = state(now.turn + 1, (x + dx[i]) * 4 + y + 1 + dy[i], 0);
			if(!valid(x + dx[i], y + dy[i])) continue;
			
			switch(next.pos)
			{
				case 1:
				{
					next.code = (p[1] + 1) * 8 + (p[2] + 1) * 64 + (1 + p[3]) * 512;
					break;
				}
				case 3:
				{
					next.code = p[0] + 1 + (p[2] + 1) * 64 + (1 + p[3]) * 512;
					break;
				}
				case 9:
				{
					next.code = p[0] + 1 + (p[1] + 1) * 8 + (1 + p[3]) * 512;
					break;
				}
				case 11:
				{
					next.code = p[0] + 1 + (p[1] + 1) * 8 + (1 + p[2]) * 64;
					break;
				}
				default:
				{
					next.code = p[0] + 1 + (p[1] + 1) * 8 + (p[2] + 1) * 64 + (1 + p[3]) * 512;
					break;
				}
			}
			if(!valid(next)) continue;
			if(next.turn == n)return true;
			vis[next.turn][next.pos][next.code] = true;
			Q.push(next);
		}
	}
	return false;
}
int main()
{
	while(scanf("%d", &n) == 1)
	{
		if(!n) return 0;
		memset(day, false, sizeof(day));
		for(int i = 1; i <= n; ++ i)
			for(int j = 1; j <= 16; ++ j) scanf("%d", &day[i][j]);
		printf("%d
", bfs());
	}
	return 0;
}/*
challenge : 1. the design of state
   			2. the extention of states
   			3. the pictures of position
*/
原文地址:https://www.cnblogs.com/zach20040914/p/12633195.html