POJ-1062 昂贵的聘礼 解题报告
Dijstra算法
解题思路
通过题意,我们可以很明显的看出来,物品的交换流程可以构成一个有向图,而且这个图是有边权的。
构建这个图的过程如下:
因为每个物品都有相应的替代物品,所以我们可以在替代物品和该物品之间建立一条边,从替代物品指向该物品,并且边上的权值为优惠价格。这样建完所有的边之后,我们可以创造一个起点,这个起点对所有的物品都有一个出边,并且边上的权值为该物品的原价。最终我们的结果肯定是一个从起点到编号为1的物品的最短路。
通过上面的分析,现在我们的问题是如何将每个物品主人的等级考虑进去,根据题意我们了解到,我们最终的结果是在那条最短路上,最高的等级与最低的等级之间的差不能超过M,这里是特别容易弄错的地方,我之前以为是如果A与B之间的等级差小于M,B与C之间的等级差小于M就能一直从A交换到C……
解题关键:最终的我们得到的最短路,里面肯定是有一个点X的等级是最低的,那么我们可以在原图上找到所有的比这个X点等级高的,而且那些点与X点之间的等级差必须小于等于M,最终的路径肯定是这些点里面产生的。所以我们枚举每一个可能的点,将这个被枚举的点当作X点,然后找到所有满足上述条件的其他点,在这些点之间跑单源最短路。每次枚举X点我都能得到一个最短路径值,最终我们取最小的路径值便是结果。
解题代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 110;
const int INF = 0X3fffffff;
int M,N;
int dis[MAXN][MAXN];
int cost[MAXN];
bool vis[MAXN];
struct Node {
int price;
int level;
int itemCount;
int itemNum[MAXN];
int itemPrice[MAXN];
}node[MAXN];
void initDis() {
for(int i = 0; i <= N; i++) {
dis[i][i] = 0;
for(int j = i+1; j <= N; j++) {
dis[i][j] = dis[j][i] = INF;
}
}
}
void initCost() {
cost[0] = 0;
for(int i = 1; i <= N; i++) {
cost[i] = INF;
}
}
void buildGraph() {
for(int i = 1; i <= N; i++) {
dis[0][i] = node[i].price;
for(int j = 0; j < node[i].itemCount; j++) {
int id = node[i].itemNum[j];
int val = node[i].itemPrice[j];
dis[id][i] = val;
}
}
}
int dijkstra(int x) {
memset(vis, false, sizeof(vis));
initCost();
for(int i = 1; i <= N; i++) {
if(node[x].level <= node[i].level && node[i].level-node[x].level <= M) {
cost[i] = dis[0][i];
}
}
vis[0] = true;
for(int i = 1; i <= N; i++) {
int _min = INF;
int p = -1;
for(int j = 0; j <= N; j++) {
if(!vis[j] && _min > cost[j]) {
p = j;
_min = cost[j];
}
}
if(-1 == p || INF == _min)continue;
vis[p] = true;
for(int j = 0; j <= N; j++) {
if(!vis[j] && cost[j] > cost[p]+dis[p][j] &&
node[x].level <= node[j].level && node[j].level-node[x].level <= M) {
cost[j] = cost[p]+dis[p][j];
}
}
}
return cost[1];
}
int main() {
while(~scanf("%d%d", &M, &N)) {
initDis();
for(int i = 1; i <= N; i++) {
scanf("%d%d%d", &node[i].price, &node[i].level, &node[i].itemCount);
for(int j = 0; j < node[i].itemCount; j++) {
scanf("%d%d", &node[i].itemNum[j], &node[i].itemPrice[j]);
}
}
buildGraph();
int ans = INF;
for(int i = 1; i <= N; i++) {
ans = min(dijkstra(i), ans);
}
printf("%d\n", ans);
}
return 0;
}