您的位置:首页 > 其它

POJ2044 Weather Forecast(DFS)

2016-03-28 13:37 447 查看
假设你可以控制天气,你拥有一片2*2大小的云,在云覆盖的土地上无论何时都在下雨,否则一直是晴天。在一个国家的土地上你需要移动这篇云,第一天时云在(2,2)(2,3)(3,2)(3,3)上。现在有n(n≤365)n(n \leq 365)天,每天每块土地有些活动,1表示这块土地在这天有节日,不能下雨。除此之外,不能有一块土地连续超过6天不下雨。

若只把云看做左上角的点,那么一共只有9种位置状态。

还需要标记一块土地是否下雨,本来有16个格子,实际上用4个变量就可以保存,4*4的格子平均分成4块就好了。(讲得不如网上其他题解清楚。。)

然后就用vis[i][s][a][b][c][d]表示状态,表示第i天,云的位置在s,(1,1)(1,3)(3,1)(3,3)分别有a,b,c,d天没有下雨。

#include<cstdio>
#include<cstring>
using namespace std;
bool vis[366][10][8][8][8][8],flag;
int sunny[366],n;
int dir[10][2] = {{0,0},{1,0},{-1,0},{0,1},{0,-1},{2,0},{-2,0},{0,2},{0,-2}};
int pos[12] = {0,1,2,3,0,4,5,6,0,7,8,9};
bool check(int day,int x,int y,int sun[])
{
if(x < 1||x > 3||y < 1||y > 3) return false;
if(sun[0] >= 7||sun[1] >= 7||sun[2] >= 7||sun[3] >= 7) return false;
int a = (x-1)*4+y;
int b = x*4+y;
int c = (x-1)*4+y+1;
int d = x*4+y+1;
if((1<<(a-1))&sunny[day]) return false;
if((1<<(b-1))&sunny[day]) return false;
if((1<<(c-1))&sunny[day]) return false;
if((1<<(d-1))&sunny[day]) return false;
if(vis[day][pos[a]][sun[0]][sun[1]][sun[2]][sun[3]]) return false;
return true;
}
void dfs(int day,int x,int y,int sun[])
{
if(day >= n)
{
flag = 1; return;
}
if(flag) return;
int b[4];
for(int i = 0; i < 9; i++)
{
if(day == 0&&i) break;
if(flag) return;
int tx = x+dir[i][0],ty = y+dir[i][1],td = day+1;
for(int j = 0; j < 4; j++) b[j] = sun[j]+1;
if(tx == 1&&ty == 1) b[0] = 0;
if(tx == 1&&ty == 3) b[1] = 0;
if(tx == 3&&ty == 1) b[2] = 0;
if(tx == 3&&ty == 3) b[3] = 0;
if(check(td,tx,ty,b))
{
vis[pos[(tx-1)*4+ty]][b[0]][b[1]][b[2]][b[3]] = 1;
dfs(td,tx,ty,b);
}
}
}
void init()
{
flag = 0;
memset(vis,0,sizeof vis);
memset(sunny,0,sizeof sunny);
}
int main()
{
while(scanf("%d",&n) != EOF&&n)
{
init();
int c;
for(int i = 1; i <= n; i++)
for(int j = 0; j < 16; j++)
{
scanf("%d",&c);
if(c) sunny[i] = sunny[i]|(1<<j);
}
int a[4] = {};
dfs(0,2,2,a);
printf("%d\n",flag);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: