HDU_1175 连连看(DFS)

  此题做的相当爽,为什么爽呢,因为。。。连带TLE, RE, WA。总共错了11次。。。有一个地方没考虑清楚,然后再怎么剪枝都WA,最后ZZ一句话惊醒梦中人,总于A了。

思路:

这题要求方向改变次数。用一个变量记录上一次的方向,与下一次向比较,如果不同则加1。

My Code:

#include <iostream>
#include
<cstdio>
#include
<cstring>
#define ud 1; //标记上下方向
#define lr 2; //标记左右方向

using namespace std;


int map[1005][1001]; //存放每次询问简化后的图
int num[1005][1001]; //存放输入数据
int cost[1005][1001]; //存放到[i, j]位置最小拐弯次数。
int d[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; //四个方向
int n, m, flag;
int ei, ej, si, sj, ti, tj; //终点,起点,标记起点

void dfs(int si, int sj, int step, int dir)
{
int i, tdir, tmp;
if(si == ei && sj == ej && step <= 2) flag = 1; //满足条件
if(flag) return;

for(i = 0; i < 4; i++)
{
int x = si + d[i][0];
int y = sj + d[i][1];
tdir
= dir;

if(x > 0 && x <= n && y > 0 && y <= m && map[x][y] != -1)
{
if(d[i][1] == 0 && !(si == ti && sj == tj)) tdir = lr; //如果当前左右移动且起始点不是起点。
if(d[i][0] == 0 && !(si == ti && sj == tj)) tdir = ud; //如果当前上下移动且起始点不是起点。

if(tdir != dir) tmp = step+1; //与上次的方向不同
else tmp = step;

if(d[i][1] == 0) tdir = lr; //标记本次的方向,主要就是错在这里!!!众看官好好体会
if(d[i][0] == 0) tdir = ud;

if(tmp < cost[x][y]) //小于到[x, y]的最小拐弯次数
{
cost[x][y]
= tmp;
map[x][y]
= -1;
dfs(x, y, tmp, tdir);
map[x][y]
= 0;
}
}
}
}

int main()
{
//freopen("data.in", "r", stdin);

int i, j, p;
while(scanf("%d%d", &n, &m), n||m)
{
for(i = 1; i <= n; i++)
for(j = 1; j <= m; j++)
scanf(
"%d", &num[i][j]);

scanf(
"%d", &p);
while(p--)
{
scanf(
"%d%d%d%d", &si, &sj, &ei, &ej);
ti
= si; tj = sj; //记录起点
if(si > n || sj > m || ei > n || ej > m) //越界
{
printf(
"NO\n"); continue;
}
if(num[si][sj] != num[ei][ej] || num[si][sj] == 0) //不符合游戏条件
{
printf(
"NO\n"); continue;
}
else
{
for(i = 1; i <= n; i++) //把当前询问的合法图扣出来
{
for(j = 1; j <= m; j++)
{
if(num[i][j] == 0 || (i == si && j == sj) || (i == ei && j == ej))
map[i][j]
= 0;
else
map[i][j]
= -1;
cost[i][j]
= 3; //初始化为3
}
}
flag
= 0;
dfs(si, sj,
0, 0);
if(flag)
printf(
"YES\n");
else
printf(
"NO\n");
}
}
}
return 0;
}

你可能感兴趣的:(HDU)