[Usaco2008 Open] Clear And Present Danger 寻宝之路

11 篇文章 0 订阅
7 篇文章 0 订阅

Problem

Time Limit: 1 Sec Memory Limit: 128 MB
Description
农夫约翰正驾驶一条小艇在牛勒比海上航行.
海上有N(1≤N≤100)个岛屿,用1到N编号.约翰从1号小岛出发,最后到达N号小岛.一张藏宝图上说,如果他的路程上经过的小岛依次出现了Ai,A2,…,AM(2≤M≤10000)这样的序列(不一定相邻),那他最终就能找到古老的宝藏. 但是,由于牛勒比海有海盗出没.约翰知道任意两个岛屿之间的航线上海盗出没的概率,他用一个危险指数Dij(0≤Dij≤100000)来描述.他希望他的寻宝活动经过的航线危险指数之和最小.那么,在找到宝藏的前提下,这个最小的危险指数是多少呢?
Input
第1行输入N和M,之后M行一行一个整数表示A序列,之后输入一个NxN的方阵,表示两两岛屿之间航线的危险指数.数据保证Dij=Dji,Dii=0.
Output
最小的危险指数和.
Sample Input

3 4
1
2
1
3
0 5 1
5 0 2
1 2 0

/*INPUT DETAILS:
There are 3 islands and the treasure map requires Farmer John to
visit a sequence of 4 islands in order: island 1, island 2, island
1 again, and finally island 3. The danger ratings of the paths are
given: the paths (1, 2); (2, 3); (3, 1) and the reverse paths have
danger ratings of 5, 2, and 1, respectively.*/

Sample Output

7
/*OUTPUT DETAILS:
He can get the treasure with a total danger of 7 by traveling in
the sequence of islands 1, 3, 2, 3, 1, and 3. The cow map's requirement
(1, 2, 1, and 3) is satisfied by this route. We avoid the path
between islands 1 and 2 because it has a large danger rating.*/

HINT

题解:

此题裸裸的最短路,求最小危险值其实就是最短路,但这里的最短路是有要求的“规定路线”,且数据范围不大,可用Floyed算法轻松解决,但要注意在求最后答案时要注意方法。

AC代码如下

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#define ri register int //卡常数
using namespace std;

int n,m,ans;
int a[10001],d[101][101];

inline void read(int &x) //quickly_read快读
{
	x=0;int f=1;char ch=getchar();
	while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	x*=f;
}

int main()
{
	read(n),read(m);
	for (ri i=1;i<=m;++i)
		read(a[i]);
	for (ri i=1;i<=n;++i)
		for (ri j=1;j<=n;++j)
			read(d[i][j]);
	for (ri k=1;k<=n;++k)
		for (ri u=1;u<=n;++u)
			for (ri v=1;v<=n;++v)
				if (k!=u&&u!=v&&v!=k)
					d[u][v]=min(d[u][v],d[u][k]+d[k][v]);
	//朴素的Floyed算法
	for (ri i=2;i<=m;++i) ans+=d[a[i-1]][a[i]];
	//注意这里的求解,它已经要求了最短路经过的顺序
	//所以除去从1到路径的头点以及路径尾点到n,由此2 to m循环
	ans+=d[1][a[1]]+d[a[m]][n];
	//将未加上的危险指数1 to a[1]及a[m] to m加上
	printf("%d",ans);
	return 0;
}

如有不当之处请各位神犇及时指出!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值