[洛谷]P2937 [USACO09JAN]激光电话Laserphones (#搜索)

题意翻译

题目描述

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值