题意:给你一个n x m的矩阵,其中’.‘可达,’#‘表示障碍。每次只能向右或者向下走,问至少添加多少个’#’,能够使得自(0, 0)走不到(n-1, m-1)。
一开始这题把我吓住了,觉得是不是要搞出所有可行的通路,然后找出重合的公共点,把这一点堵死。但其实不用这么麻烦,因为题目规定了移动方向只能是向下或者向右,所以答案只会是0,1,2三者其中之一。
但是想出这一点之后,还是存在问题,即使(0, 1)(1, 0)都为’.’,但由于地图不同,有可能他们最后都无法到达(n-1, m-1)。所以一直没想出该怎么取求。
赛后看题解,用两遍dfs,走过就标记’#’,这里也卡了好久。感觉自己还是基本功不扎实,对搜索理解的不透彻。我当时卡就卡在怎么记录这一路走过点的坐标,总不能用个vector,通过pair放进去,扫完了再统一标记吧?而且即使这样,因为dfs的过程中存在不可达通路,也没法判断哪些放进去哪些不放进去。
后来想到,暑假集训有个线段树+bfs的题,在每次递归之后加标记(把dfs设置成bool类型,如果返回1说明这是可行通路,那么在return的时候会一层层return回去,所以就一点点把走过的道路都加上了标记),于是就按照这个想法写。
虽然是对的,但是T在第16个样例。参考标程感觉想法是一样的,想不出为什么我就T了。研磨了半天发现了问题所在。
设置一个dfscnt变量,每次调用dfs都进行++,在程序的最后输出dfscnt。
4 5
. . . . .
. . . . #
. . . . .
. . #. .
以这组样例来讲,发现我的程序dfscnt = 22,标程dfscnt = 18。所以不难想象当测试的数据规模不断增大,和标程的效率差距也将体现的越来越明显。但是为什么会出现这种差异呢?
问题就出现在每次dfs调用加标记的地方,这是我的处理:如果dfs有结果,再沿途标记回来。
dfs(tempx, tempy);
if(ans)
{
matrix[tempx][tempy] = '#';
return;
}
这是标程的处理:不论dfs有没有结果,只要走到就标记为#。
matrix[tempx][tempy] = '#';
dfs(tempx, tempy);
if(ans)
return;
#include <bits/stdc++.h>
using namespace std;
#define MAX_N 10010 //n, m
int n, m, ans, tempx, tempy, dfscnt;//n行m列表格
char c;
int step[2][2] = { {1, 0}, {0, 1} };
vector< vector<char> > matrix;
void dfs(int x, int y)
{
dfscnt++;
//printf("x %d y %d ans %d\n", x, y, ans);
if(ans) return;
if(x == n-1 && y == m-1)
{
ans++; return;
}
for(int i = 0;i < 2;i++)
{
tempx = x, tempy = y;
tempx += step[i][0], tempy += step[i][1];
//printf("i %d tempx %d tempy %d\n", i, tempx, tempy);
if(tempx >= n || tempy >= m)
{
//printf("continue\n");
continue;
}
if(matrix[tempx][tempy] == '#')
{
//printf("continue\n");
continue;
}
//matrix[tempx][tempy] = '#';
//printf("tempx %d tempy %d\n", tempx, tempy);
matrix[tempx][tempy] = '#';
dfs(tempx, tempy);
if(ans) return;
}
return;
}
int main()
{
scanf("%d %d", &n, &m);//n行m列
matrix.resize(n);//n*m
for(int i = 0;i < n;i++)//行
{
matrix[i].resize(m);
getchar();
for(int j = 0;j < m;j++)//列
{
scanf("%c", &c);
matrix[i][j] = c;
}
}
ans = 0;
dfs(0, 0);
if(ans)
{
//printf("here\n");
ans = 0;
matrix[n-1][m-1] = '.';
dfs(0, 0);
if(ans)
printf("2\n");
else
printf("1\n");
}
else
printf("0\n");
printf("dfscnt = %d\n", dfscnt);
return 0;
}