/*题目大意:这道题实际上就是图的最短路径问题
解题思路:建图, 结点为每件物品,把探险者也看成一个入度为零的节点,是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;
}
POJ 1062 DijStra 变形 枚举
最新推荐文章于 2016-12-02 02:11:33 发布