poj1062(dijkstra+枚举)

           题目链接:http://poj.org/problem?id=1062

       题目为中文,打开链接阅读即可。

       注意点:驸马在进行一系列交换的时候,会与多种等级的人交换,要求的是其中最大等级和最小等级的差不能大于M(或者任意两点的等级差不能大于M)。

         开始使用Floyd写,但是发现等级差很难控制,做了长时间后,看了大牛的代码,发现使用Dijkstra+枚举,可以很好的控制等级差,唉,大牛就是大牛,自己还要努力!!

         枚举等级差分析:

                 这一系列的等级如果满足某个区间[a,b],就能满足等级差要求。怎么确定这个区间呢,题意知道国王要出现在任何一条交换路径,国王的等级为rank[1],先可以想到参与交换的等级必须在区间[rank[1]-M,rang[1]+M]内,但是在这个区间内有等级差大于M的情况,但是可以将这个区间分为[rank[1]-M,rank[1]],[rank[1]-M+1,rank[1]+1],[rank[1]-M+2,rank[1]+2].......[rank[1],rank[1]+M],这些子区间涵盖了区间[rank[1]-M,rank[1]+M],而且在这些区间里面所有的等级差都不会超过M,所以只需要枚举这些区间,求出各个区间内最小cost,然后取其中最小的(mincost)即可。

代码:

#include<stdio.h>
#include<string.h>
#define INF 10000000
int map[101][101];
int rank[101],v[101];
int dis[101],inrank[101],visted[101];
int M,N;
int dijkstra()
{
	int i,j;
	int u,min;
	
	memset(visted,0,sizeof(visted));

	dis[1]=0;
	for(i=2;i<=N;i++)
		dis[i]=INF;
	for(i=1;i<=N;i++)
	{
        min=INF;
		for(j=1;j<=N;j++)
			if(min>dis[j] && inrank[j] && !visted[j])
			{
				min=dis[j];
				u=j;
			}
			
			visted[u]=1;

		for(j=1;j<=N;j++)
			if(dis[j]>dis[u]+map[u][j] && inrank[j])
				dis[j]=dis[u]+map[u][j];

	}
	min=INF;
	
	for(i=1;i<=N;i++)
		if(min>dis[i]+v[i])
			min=dis[i]+v[i];
	
		return min;
}
void main()
{
    int i,j;
	int n,renum,reprice;
	int cost,mincost=INF;
	scanf("%d%d",&M,&N);
	for(i=0;i<=N;i++)
		for(j=0;j<=N;j++)
			if(i==j)
				map[i][j]=0;
			else 
				map[i][j]=INF;
	for(i=1;i<=N;i++)
	{
       scanf("%d%d%d",&v[i],&rank[i],&n);
	    for(j=1;j<=n;j++)
	   {
           scanf("%d%d",&renum,&reprice);
		   map[i][renum]=reprice;
		}
	}
    for(i=0;i<=M;i++)
	{
		memset(inrank,0,sizeof(inrank));
		for(j=1;j<=N;j++)
		{
			if(rank[j]>=rank[1]-M+i && rank[j]<=rank[1]+i)
				inrank[j]=1;
		}
		cost=dijkstra();
        if(mincost>cost)
			mincost=cost;
	}
	printf("%d\n",mincost);
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值