poj1062dijkstra

来源:互联网 发布:广东省大数据产业园 编辑:程序博客网 时间:2024/05/18 03:49
思路:以物品为结点,物品之间的优惠价格为边权值建图,酋长10000金币当做0号结点,题意就是求图中各结点到0号结点的最短路长度,再加上终点处物品的价值,恰好就是探险家经过这个物品买卖途径所需要付出的金钱。用dijkstra算法求出单源最短路径,从各个结点的最短路径中选出最短的那条就是答案。基本还是经典最短路问题,但做了一点小小变形主要是:
1 有结点等级限制,需要枚举等级
2 把终点的物品价值计入最短路径中去,并且找最小的最短路径输出
3 要注意是单向图,即物品替换关系是单向的

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

const int maxn = 110;
const int INF = 200000000;

int w[maxn][maxn]; //w[i][j]表示物品i换j的花费
int dist[maxn]; //dist[i]表示起点到i的花费
bool vis[maxn];

int level[maxn], value[maxn]; //等级与价值
bool can_change[maxn]; //满足等级限制的标记数组
int limit_level, n; //limit_level 表示限制的等级

int Dijkstra()
{
int mini_cost = INF;
memset(vis,false,sizeof(vis)); //清除所有点的标号
for(int i=1; i<=n; i++)
dist[i] = INF; //设d[1] = 0,其它为 INF
dist[1] = 0; //(此处还未加上进入改点的花费)自己换自己为0
for(int i=1; i<=n; i++) //循环n 次
{
int x, m = INF;
for(int y=1; y<=n; y++)
{
//在所有未标号且满足等级限制的点中选出 d值最小的点 x
if(!vis[y] && dist[y] <= m && can_change[y])
m = dist[x=y];
}
vis[x] = true; //标记点x
for(int y=1; y<=n; y++) // 对于从x出发的所有边 (x, y)更新dist
{
if(can_change[y]) //若满足等级限制
dist[y] = min(dist[y], dist[x]+w[x][y]);
}
}
for(int y=1; y<=n; y++)
{
//对于每个dist[y]还要满足进入改点的花费
dist[y] += value[y];
mini_cost = min(mini_cost,dist[y]);
}
return mini_cost; //返回最小值
}
int main()
{
scanf("%d%d", &limit_level, &n);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(i==j) w[i][j] = 0; //从自己到自己花费为0
else w[i][j] = INF;
}
}
for(int i=1; i<=n; i++)
{
int change;
scanf("%d%d%d", &value[i], &level[i], &change);
for(int j=1; j<=change; j++)
{
int y,Value;
scanf("%d%d", &y, &Value);
w[i][y] = Value;
}
}
int King_level = level[1]; //酋长的等级
int m, minicost = INF;
for(int i=0; i<=limit_level; i++) //枚举
{
memset(can_change,false,sizeof(can_change));
for(int j=1; j<=n; j++)
{
//枚举等级允许的范围
if(level[j] >=King_level-limit_level+i && level[j]<=King_level+i)
can_change[j] = true;
}
minicost = min(minicost, Dijkstra());
}
printf("%d\n",minicost);
return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

const int LEN = 110;
const int INF = 200000000;
int w[LEN][LEN], dist[LEN], vis[LEN], level[LEN], value[LEN], can_change[LEN], limit_level, n;

int Dijkstra()
{
int mini_cost = INF;
memset(vis, false, sizeof(vis));
for (int i=1; i<=n; i++)
dist[i] = INF;
dist[1] = 0;
for (int i=1; i<=n; i++)
{
int x, m = INF;
for (int y=1; y<=n; y++)
{
if ( !vis[y] && dist[y]<=m && can_change[y] )
m = dist[x=y];
}
vis[x] = true;
for (int y=1; y<=n; y++)
{
if ( can_change[y] )
dist[y] = min(dist[y], dist[x]+w[x][y]);
}
}
for (int y=1; y<=n; y++)
{
dist[y] += value[y];
mini_cost = min(mini_cost, dist[y]);
}
return mini_cost;
}

int main()
{
scanf("%d%d", &limit_level, &n);
for (int i=1; i<=n; i++)
{
for (int j=1; j<=n; j++)
{
if ( i==j ) w[i][j] = 0;
else w[i][j] = INF;
}
}
for (int i=1; i<=n; i++)
{
int change;
scanf("%d%d%d", &value[i], &level[i], &change);
for (int j=1; j<=change; j++)
{
int y, val;
scanf("%d%d", &y, &val);
w[i][y] = val;
}
}
int king_level = level[1];
int m, minicost = INF;
for (int i=0; i<=limit_level; i++)
{
memset(can_change, false, sizeof(can_change));
for (int j=1; j<=n; j++)
{
if ( level[j] >=king_level-limit_level+i &&
level[j]<=king_level+i )
can_change[j] = true;
}
minicost = min(minicost, Dijkstra());
}
printf("%d\n", minicost);
return 0;
}

原创粉丝点击