poj 3411 Paid Roads

9 篇文章 0 订阅

题目大意

有n座城市和m(1<=n,m<=10)条路。现在要从城市1到城市n。有些路是要收费的,从a城市到b城市,如果之前到过c城市,那么只要付P的钱,如果没有去过就付R的钱。求的是最少要花多少钱。

注意:路径是有向的。

算法思想:dfs可过。

提示:最优解法不是每条路只允许走一遍,可能有情况满足某条路i的p比r小很多,而且走c城市再回来走总钱数比直接走、付费r更省,此时只走i的“最短路”就不是最优解。每条路都可以重复走,那么为了防止出现死循环,当判断出途中有环时应当跳出。当某座城市走过3次以上时,可以判定陷入环中,应当跳出(至于为啥是3次。。。参考其他博主的文章,这与m的取值有关,本题中m<=10所以是3)。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>

using namespace std;
const int inf=21000000;
int n,m,ans,mx,vis[15],v[15],num=0;  //因为判断是否能走的条件是走过的次数,这里vis[]用int型;
struct mc
{
	int a,b,c,p,r,ne;
}e[15];

void put(int a,int b,int c,int p,int r)
{
	num++;
	e[num].a=a;
	e[num].b=b;
	e[num].c=c;
	e[num].p=p;
	e[num].r=r;
	e[num].ne=v[a];
	v[a]=num;
}

void dfs(int i,int ans)  //dfs(当前城市,当前花费);
{
	if (i==n)    //到达目的地,判断这条路径是否最优;
	{
		if (ans<mx) mx=ans;
		return;
	}
	for (int l=v[i];l;l=e[l].ne)
	{
		if (vis[e[l].b]<=3)  //判环,确定是否可以继续走;
		{
			vis[e[l].b]++;
			if (vis[e[l].c])    //满足要求,这条路付费p;
		          dfs(e[l].b,ans+e[l].p);
    		        else     //不满足要求,这条路付费r;
	    		  dfs(e[l].b,ans+e[l].r);
			vis[e[l].b]--;    //回溯;
		}
	}
	return;
}

int main()
{
	int a,b,c,p,r;
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d%d%d%d",&a,&b,&c,&p,&r);
		put(a,b,c,p,r);
	}
	ans=0; mx=inf;
	vis[1]=1;
	dfs(1,0);
	if (mx==inf) printf("impossible");  //最小花费未被更新,说明不能走到;
	else printf("%d",mx);
	return 0;
 } 




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值