题意翻译
题目描述
The cows have a new laser-based system so they can have casual conversations while out in the pasture which is modeled as a W x H grid of points (1 <= W <= 100; 1 <= H <= 100).
The system requires a sort of line-of-sight connectivity in order to sustain communication. The pasture, of course, has rocks and trees that disrupt the communication but the cows have purchased diagonal mirrors ('/' and '' below) that deflect the laser beam through a 90 degree turn. Below is a map that illustrates the
problem.
H is 8 and W is 7 for this map. The two communicating cows are notated as 'C's; rocks and other blocking elements are notated as '*'s:
7 . . . . . . . 7 . . . . . . .
6 . . . . . . C 6 . . . . . /-C
5 . . . . . . * 5 . . . . . | *
4 * * * * * . * 4 * * * * * | *
3 . . . . * . . 3 . . . . * | .
2 . . . . * . . 2 . . . . * | .
1 . C . . * . . 1 . C . . * | .
0 . . . . . . . 0 . \-------/ .
0 1 2 3 4 5 6 0 1 2 3 4 5 6
Determine the minimum number of mirrors M that must be installed to maintain laser communication between the two cows, a feat which is always possible in the given test data.
奶牛们都改用激光进行通讯了.
在W*H的牧场上,一些地方有树木和石头遮挡激光,所以,奶 牛打算使用对角镜来进行激光通讯.两只奶牛的位置是固定的,对角镜能把光线旋转90度.
输入格式
* Line 1: Two space separated integers: W and H
* Lines 2..H+1: The entire pasture.
输出格式
* Line 1: A single integer: M
输入输出样例
输入 #1
7 8 ....... ......C ......* *****.* ....*.. ....*.. .C..*.. .......
输出 #1
3
思路
典型的01最短路问题,比较好的方法是用bfs。这里用的dfs求,主要是想练习dfs。
首先考虑dfs,如果要换方向就把答案+1,至于镜子怎么摆放的我们不管,反正只要换方向了肯定需要一个镜子。到达另一个奶牛的时候更新答案,取最小值即可。
每次搜的时候按照之前的方向搜,然后再尝试其他方向搜。这样能尽快找到最优解。
但是仍然会TLE。考虑使用记忆化搜索。令dp[x][y][direct]为表示到点(x,y)并且前一次转弯位direct时最小转弯次数。
#include <stdio.h>
#include <iostream>
#include <memory.h>
using namespace std;
int tox[5]={0,1,0,-1,0},toy[5]={0,0,1,0,-1};
int n,m,s(9999999),cnt,dp[501][501][5];
char a[501][501];
bool vis[501][501];
void dfs(int x,int y,int direct,int times)//x,y坐标,direct方向,times转弯次数
{
if(direct!=-1 && dp[x][y][direct]<=times) return;
if(direct!=-1) dp[x][y][direct]=times;//记录最优解
if(a[x][y]=='C')
{
s=min(s,times);
return;
}
register int i,j,x1,y1;
if(direct!=-1)//先同方向搜索
{
x1=x+tox[direct];
y1=y+toy[direct];
if(x1>=1 && x1<=n && y1>=1 && y1<=m && vis[x1][y1]==0 && a[x1][y1]!='*')
{
vis[x1][y1]=1;
dfs(x1,y1,direct,times);//肯定方向相同,不用拐弯
vis[x1][y1]=0;
}
}
for(i=1;i<=4;i++)//枚举方向
{
if(i!=direct)
{
x1=x+tox[i];
y1=y+toy[i];
if(x1>=1 && x1<=n && y1>=1 && y1<=m && vis[x1][y1]==0 && a[x1][y1]!='*')
{
vis[x1][y1]=1;
if(direct!=-1)//换一个方向就要加一个镜子
dfs(x1,y1,i,times+1);
else//如果等于-1的话,还是意味着同方向。这个特判主要针对于一开始激光怎么走
dfs(x1,y1,i,times);
vis[x1][y1]=0;
}
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
register int i,j,k;
cin>>m>>n;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>a[i][j];
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(a[i][j]=='C')
{
memset(dp,999999,sizeof(dp));
vis[i][j]=1;
a[i][j]='*';//防止被认为是其他奶牛
dfs(i,j,-1,0);//由于一开始不好确定方向所以direct先为-1
cout<<s<<endl;
return 0;
}
}
}
return 0;
}