题目:http://poj.org/problem?id=1062
AC代码(C++):
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <queue>
#include <math.h>
#include <string>
#include <string.h>
#include <bitset>
#define INF 0xfffffff
using namespace std;
struct ITEM{
int p;
int l;
};
int m, n;
ITEM* item;
int map[105][105];
int Min;
bool vis[105];
int HL,LL;
void dfs(int num, int dist){
vis[num] = true;
int tmpHL = HL;
int tmpLL = LL;
if(item[num].l+m<HL)HL=item[num].l+m;
if(item[num].l-m>LL)LL=item[num].l-m;
for(int i = 1; i <= n; i++){
if(map[num][i]==-1||vis[i]==true||item[i].l>HL||item[i].l<LL)continue;
int tmp = item[i].p + dist + map[num][i];
if(tmp<Min)Min = tmp;
dfs(i, dist+map[num][i]);
}
HL = tmpHL;
LL = tmpLL;
vis[num] = false;
}
int main(){
memset(map,INF,sizeof(map));
memset(vis,false,sizeof(vis));
cin>>m>>n;
item = new ITEM[n+1];
for(int i = 1; i <= n; i++){
int x;
cin>>item[i].p>>item[i].l>>x;
for(int j = 0; j < x; j++){
int t,v;
cin>>t>>v;
map[i][t] = v;
}
}
Min = item[1].p;
HL = item[1].l + m;
LL = item[1].l - m;
dfs(1,0);
cout<<Min;
}
总结:
1.题目的意思看似很复杂其实很简单, 从物品1开始, 有替代品就生成一条边, 边的权值就是优惠价, 边的另一头就是替代的物品, 再以这个替代物品继续往下生成, 知道没有替代品. 于是得到了一个图, 我们只需要从物品1开始遍历每个节点(用什么方法都行), 在到达每个节点的时候计算到这一节点时的总费用(即经过的所有边+这个节点物品本身的价值), 然后与全局最小值Min比较赋值, 遍历一遍后得到的Min就是答案.
2.这题有几个坑点, 一个是每个物品的等级L, 网上有些人的代码直接拿L跟物品1的L比较, 这是不对的(至少我提交不行, 不知道他们是怎么弄成可以的). 我的处理办法是取一个区间, 深搜到达一个节点时更新一次区间范围, 离开节点时还原, 具体操作见代码.
3.还有一个坑点是, 不要开数组来保存边信息, 测试里会有很多物品+每个物品有大量替代, 导致MLE. 解决办法是用二维数组map来保存边信息.