POJ 1062 DijStra 变形 枚举

/*题目大意:这道题实际上就是图的最短路径问题

解题思路:建图, 结点为每件物品,把探险者也看成一个入度为零的节点,是n + 1结点之一,探险者到其他物品的直接连线的权值为物品的原始价格,
其他 i -> j的边的权值为探险者获得i后换j的优惠价格。
应该注意的是,由于等级限制,如果你和level[1] - k级别的人交易过,那么你最多只能和level[1] - k + m进行交易,因此我们要对这m个等级范围进行枚举,
每次枚举只考虑该等级范围内的点,并求出n + 1点到1点的最小值(最短路,dijkstra),再记录多次枚举得到的最小值,最后的最小值即为所求答案。

注意点:

1.代码中涉及到了不少的数组,所以对于某些有特定含义的数组一定要进行初始化,以免在后面的数值比较时出错

2.在设置一个很大的数字时要小心,最好是不要设置为最大整型数Integer.MAX_VALUE,因为一旦它参与运算就会出现
  不可预料的错误,如果它只是进行数值比较的话,那么是可以的
3.这道题目解法很多,建图可以用邻接矩阵也可以用邻接表,求最短路径可以用Dijkstra 也可以用其他的方法(例如:spfa)

**/

#include <stdio.h>
#include <iostream>
using namespace std;

#define INF 1000000
int map[101][101];//matrix表示图的邻接矩阵【有向图】
int level[101];//level
int dist[101];//distance从0到该点的权值
int mark[101];//mark 标记是否可以和他进行交易
int m;// level distance
int n;// goods number
int ans;//result

void dijstra(){
     int i,j,k,start,min;
     ans=INF;
     for(k=0;k<=m;k++){//枚举等级差
        for(i=1;i<=n;i++){
           if(level[i]-level[1]<=k&&level[1]-level[i]<=m-k){
               mark[i]=1;//表示可以进行交易
               dist[i]=map[0][i];                                                 
           }else{
                mark[i]=0;      
                dist[i]=INF;
           }                  
                          
        } 
      
     
     for(i=1;i<=n;i++){
       start=1;
       min=INF;
       for(j=1;j<=n;j++){//得到距离最短的点
          if(mark[j]==1&&dist[j]<min){//可以访问的点 中距离最近的 
             start=j;
             min=dist[j];                            
          } 
        }                  
        mark[start]=0;//将刚刚得到距离最短的点标记为不能访问
        for(j=1;j<=n;j++){
        //由于新点的加入,要修改距离值【从0开始到该点的最短距离】
        if(mark[j]==1&&dist[j]>dist[start]+map[start][j])                  
            dist[j]=dist[start]+map[start][j];              
        } 
                       
     }
     if(ans>dist[1])
      ans=dist[1];
  }
  cout<<ans<<endl;
} 
 
int main(){
    cin>>m>>n;
    int i,j,k,t;
    for(i=0;i<=n;i++)
      for(j=0;j<=n;j++)
        // map[i][j] = (i == j ? 0 : INF);//图的初始化,注意对角线初始化为0,从自己出发到自己的花费为0
        map[i][j]=INF;
    for(i=1;i<=n;i++)
    {
       cin>>map[0][i]>>level[i];//价格和等级
       cin>>t;//替代品总数
       for(j=1;j<=t;j++)
        {  //cin>>k>>map[k][i];出现Runtime Error 
            cin>>k;
           cin>>map[k][i];//建立有权边
        }      
    }
    dijstra(); 
    system("pause");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值