//===============================================//
// poj:1062 昂贵的聘礼
// dijkstra + 枚举 AC
// 最短路径问题
//==============================================//
#include <stdio.h>
#include <string.h>
const int NUM = 105; //题目要求的的节点范围是100
const int MAX_INT = 0x3f3f3f; //用于标识无法连接的点即一个无穷大值
int map[NUM][NUM], value[NUM], lev[NUM]; //图矩阵, 物品价值, 等级数组
int lim[NUM]; //用于每次枚举一个范围的等级标识数组,此题由等级将图划分为若干子图
int M, N; //等级限制,物品个数
int Dijkstra();
int main()
{
int i, j;
int t;
int ans; //最后结果
int re; //通过一次dijikstra计算后得到的一个结果
while (scanf("%d %d", &M, &N) != EOF)
{
memset(map, MAX_INT, sizeof(map));
//所有物品到自己的权值为0
for (i=0; i<=N; i++)
{
map[i][i] = 0;
}
//构图
for (i=1; i<=N; i++)
{
scanf("%d %d %d", &value[i], &lev[i], &t);
for (j=0; j<t; j++)
{
int m, n;
scanf("%d %d", &m, &n);
map[i][m] = n;
}
}
ans = value[1]; //在没有任何交换时,结果为酋长要求的聘金
//枚举等级范围,以酋长为等级中心则枚举 酋长等级-等级限制-->酋长等级+等级限制
//这个范围内的所有区间这样做可以避免在一个等级内出现超出等级限制的情况
//同时将问题分割为多个子问题一次进行dijikstra计算
for (i=0; i<M+1; i++)
{
memset(lim, 0, sizeof(lim));
for (j=1; j<=N; j++)
{
if (lev[j] >= lev[1] - M + i && lev[j] <= lev[1] + i)
{
lim[j] = 1;
}
}
//根据返回值选出最小的值
re = Dijkstra();
if (ans > re)
{
ans = re;
}
}
printf("%d/n", ans);
}
return 0;
}
int Dijkstra()
{
int visited[NUM] = {0};
int dist[NUM];
int i, j, k;
int pos = 1;
int res = MAX_INT;
memset(dist, MAX_INT, sizeof(dist));
for (i=1; i<=N; i++)
{
if (lim[i])
{
dist[i] = map[pos][i];
}
}
for (i=1; i<=N; i++)
{
int min = MAX_INT;
for (j=1; j<=N; j++)
{
if (!visited[j] && lim[j] && min > dist[j])
{
min = dist[j];
pos = j;
}
}
if (min == MAX_INT)
break;
visited[pos] = 1;
for (k=1; k<=N; k++)
{
if (!visited[k] && lim[k] && dist[k] > dist[pos] + map[pos][k])
{
dist[k] = dist[pos] + map[pos][k];
}
}
}
for (i=1; i<=N; i++)
{
dist[i] += value[i];
if (res > dist[i])
{
res = dist[i];
}
}
return res;
}
poj 1062 做题要细心。。。。。。dijkstra + 枚举
最新推荐文章于 2020-01-28 03:24:13 发布