vj链接:https://cn.vjudge.net/problem/OpenJ_Bailian-1062
题目可以转换为最短路线的问题,首先,关于每个物品的原价,可以假设有一个源点(设下标为0),即物品到这个源点的距离。1可以用2加x元换,那么可以用一条1到2的距离为x的路线表示,这样,问题就转换成了求1到0的最短距离。
(这样设计路线可能怪怪的,可以把方向反过来)
还有一个需要解决的问题,就是这个部落的等级问题(一开始我以为是路线上的相邻点的等级不超过m就可以,理解错了)
要求一条路径上,等级最高的点与等级最低的点的差值不超过m
我是没想出思路来,用过深搜去除路径上的不合规则的点,超时超内存。。
看了别人的思路,差值不超过m,可以假设路径上所有的点的等级都在区间[x,y],内(y-x=m)因为求1到0的路径,所以1的等级一定在区间内,所以可以从x=(1的等级) 到 x=(1的等级+m) 枚举一遍
那么大体流程如下:
读入点的信息
枚举区间,根据每个区间建立图(点的等级在区间内就在图中加入相关的线),根据这个图,求1到0的最短路线,更新最小值
输出多次最短路线的最小值
#include <cstdio>
#include <cstring>
#include <algorithm>
#define Max 2000000
using namespace std;
struct OB{
int p,l,x;
int ne_t[105];
int ne_v[105];
}ob[105];
int mp[105][105], r[105], book[105];
int m,n;
int fmi(){
int ret, mi=Max+1;
for(int i=0; i<=n; i++){
if(book[i]) continue;
if(r[i]<mi){
mi = r[i];
ret = i;
}
}
book[ret] = 1;
return ret;
}
int main()
{
while(~scanf("%d%d",&m,&n)){
for(int i=1; i<=n; i++){
scanf("%d%d%d",&ob[i].p, &ob[i].l ,&ob[i].x);
for(int j=1 ;j<=ob[i].x; j++){
scanf("%d%d",&ob[i].ne_t[j], &ob[i].ne_v[j]);
}
}
int L,H,an=Max;
for(H=ob[1].l; H<=ob[1].l+m; H++){
L = H-m;
for(int i=0; i<=n; i++){ //清零
for(int j=0; j<=n; j++){
if(i==j) mp[i][j] = 0;
else mp[i][j] = Max;
}
}
int ne;
for(int i=1; i<=n; i++){//建图
if(ob[i].l>H || ob[i].l<L) continue;
mp[i][0] = ob[i].p;
for(int j=1; j<=ob[i].x; j++){
ne = ob[i].ne_t[j];
mp[i][ne] = min(mp[i][ne],ob[i].ne_v[j]);
}
}
for(int i=0; i<=n; i++){
r[i] = mp[1][i];
}
memset(book,0,sizeof(book));
int k;
for(int i=1; i<=n; i++){ //n+1个点 n次
k = fmi();
for(int j=0; j<=n; j++){
r[j] = min(r[j],r[k]+mp[k][j]);
}
}
an = min(an,r[0]);
}
printf("%d\n",an);
}
}