此题做的相当爽,为什么爽呢,因为。。。连带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;
}