您的位置:首页 > 其它

[POJ1062] 昂贵的聘礼 枚举等级 + dijkstra

2014-04-29 22:32 381 查看
这道题的难点有两点:

1.根据题意建模,要把实际问题抽象成数学模型,才能套用dijkstra算法;

2.等级限制

问题一解决:首先,物品可以看成是用另一件物品加一些金币买到,如此,可以将物品看成点,将这些金币看成是从一点到另一点的路径,这样,就得到

物品1的花费 = 从源点(酋长)到某一点X的最短路 + 在X这一点的花费 (其花费就是X点的物品价值)

这样就转化为最短路问题,可以套用dijkstra算法。

问题二解决:因为有等级的限制,所以两点间能不能交易,即两点间有没有路还不确定,因此应该枚举所有符合等级差距限制范围的情况。

#include <iostream>
#include <cstdio>
#define MAXN 102
#define inf 100000000
using namespace std;

struct Thing
{
int val;//该物品价值
int level;//该物品主人等级
int replacen;//替换品数量
}things[MAXN];

int m,n,v,w,s,map[MAXN][MAXN],dist[MAXN];
int i,j,k;

int dijkstra(int n,int map[][MAXN],int s)
{
int visit[MAXN], maxlev, minlev;
int ans = things[0].val;
//枚举等级[things[0].level - m, things[0].level] ... [things[0].level, things[0].level + m]
for(minlev = things[0].level - m; minlev <= things[0].level; minlev ++ )
{
maxlev = minlev + m;
for (i = 0 ;i < n ;i ++ )
dist[i] = inf, visit[i] = 0;
for (dist[s] = 0,j = 0; j < n; j ++ )
{
k = -1;
for (i = 0; i < n; i ++ )
if (!visit[i] && (k == -1 || dist[i] < dist[k]) && (things[i].level >= minlev && things[i].level <= maxlev))
k = i;
visit[k] = 1;
for (i = 0 ;i < n; i ++ )
if (!visit[i] && dist[k] + map[k][i] < dist[i] && (things[i].level >= minlev && things[i].level <= maxlev))
dist[i] = dist[k] + map[k][i];
}
//把终点的val计入最短路径中去,并且找最小的最短路径输出
for(j = 0; j < n; j ++ )
dist[j] += things[j].val;
for(j = 0; j < n; j ++ )
if(dist[j] < ans)
ans = dist[j];
}
return ans;
}

int main()
{
//读入数据建图,邻接矩阵
scanf("%d%d", &m, &n);
for(i = 0; i < n; i ++ )
for(j = 0; j < n ; j ++ )
map[i][j] = inf;
for(i = 0; i < n; i ++ )
{
scanf("%d%d%d", &things[i].val, &things[i].level, &things[i].replacen);
for(j = 0; j < things[i].replacen; j ++ )
{
scanf("%d%d", &v, &w);
map[i][v - 1] = w;//注意是单向图
}
}
printf("%d\n", dijkstra(n,map,0));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: