zoukankan      html  css  js  c++  java
  • 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
    */
    
  • 相关阅读:
    ES6学习之装饰器
    ES6学习之Class
    ES6学习之Async函数
    ES6学习之Generator函数
    for循环及break和continue的区别
    ES6学习之Iterator和For...of循环
    js检测对象属性
    ES6学习之Promise
    ES6学习之Reflect
    Visual Studio references中的package找不到
  • 原文地址:https://www.cnblogs.com/zach20040914/p/12633195.html
Copyright © 2011-2022 走看看