如题:http://poj.org/problem?id=1062
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 38806 | Accepted: 11239 |
Description
为了方便起见,我们把所有的物品从1开始进行编号,酋长的允诺也看作一个物品,并且编号总是1。每个物品都有对应的价格P,主人的地位等级L,以及一系列的替代品Ti和该替代品所对应的"优惠"Vi。如果两人地位等级差距超过了M,就不能"间接交易"。你必须根据这些数据来计算出探险家最少需要多少金币才能娶到酋长的女儿。
Input
Output
Sample Input
1 4 10000 3 2 2 8000 3 5000 1000 2 1 4 200 3000 2 1 4 200 50 2 0
Sample Output
5250
Source
思路:构造图,顶点输入的N个人。建造图的时候不考虑等级导致的能否交易问题,而在最短路算法中判断。如果当前物品i可以由j物品+cost来交换,那么建立一条i指向j的有项边,权值是cost。然后dijsk,在寻找最短路的时候只有下一个要选的顶点和之前的顶点的等级的差的绝对值小于等于M才可以选,否则按照题目所说,就是间接交易。
注意:可能有人的等级大于酋长。
细心的朋友可以发现,虽然代码可以AC,但是dijsktra是贪心的,这一题的解法其实是BUG的,可能因为等级限制导致间接交易的出现导致局部最优的路径不一定是全局最优的路径,因此必须找到所有可能的路径,确保间接交易不会出现,但是肯定是超时的O(n!),只能说出题人出的数据太弱了或者出题人没有想到这个问题或是题目描述不清吧,
如果有真正对的解法希望告知。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define MAXN 105
#define INF 0x0fffffff
#define min(a,b)(a<b?a:b)
#define max(a,b)(a>b?a:b)
struct edge
{
int to,cost;
edge(int a,int b):to(a),cost(b){}
};
struct node
{
int price,degree;
}a[MAXN];
typedef pair<int,int>P; //顶点,最小距离
vector<edge>G[MAXN];
int d[MAXN];
int N,M;
int path[MAXN];
class cmp
{
public:
bool operator()(P a,P b)
{
return a.second>b.second;
}
};
void dijsktra(int s)
{
int max_d=a[s].degree;
int min_d=a[s].degree;
priority_queue<P,vector<P>,cmp>q;
int i;
for(i=0;i<MAXN;i++)
d[i]=INF;
d[s]=0;
q.push(P(s,0));
while(!q.empty())
{
P p=q.top();
q.pop();
int v=p.first;
if(p.second>d[v])
continue;
for(i=0;i<G[v].size();i++)
{
edge e=G[v][i];
if(max_d-a[e.to].degree<=M&&a[e.to].degree-min_d<=M)
if(d[e.to]>d[v]+e.cost&&abs(a[v].degree-a[e.to].degree)<=M)
{
d[e.to]=d[v]+e.cost;
q.push(P(e.to,d[e.to]));
max_d=max(max_d,a[e.to].degree);
min_d=min(min_d,a[e.to].degree);
}
}
}
}
int main()
{
// freopen("C:\\1.txt","r",stdin);
cin>>M>>N;
int i,j;
for(i=1;i<=N;i++)
{
int P,L,X;
scanf("%d%d%d",&L,&P,&X);
a[i].price=L;
a[i].degree=P;
for(j=1;j<=X;j++)
{
int v,cost;
scanf("%d%d",&v,&cost);
G[i].push_back(edge(v,cost));
}
}
dijsktra(1);
int res=INF;
for(i=1;i<=N;i++)
{
d[i]+=a[i].price;
res=min(res,d[i]);
}
printf("%d\n",res);
}