奶牛排队问题,有一些奶牛,按照次序排列,其中一些关系好的距离不能大于某个值,另外一些关系差的距离不能小于某个值,求第一只与最后一只奶牛的最长距离。
d[i] 是第i只奶牛到第一只奶牛的距离。
对于关系好的奶牛,必有d[al(i)]+dl[i]>=d[bl(i)]; 所以,为使得距离尽量远,必须正好满足众多>=号中的一个(剩下的也满足>),所以满足最短路径的定义;
对于关系不好的奶牛,必有d[ad(i)]+dd[i]<=d[bd(i),转换下就成d[ad(i)]<=d[bd(i)+(-dd[i]), 同上,满足对端路径定义,只不过讲距离取反;
其实,这是一个典型的差分系统,当然,线性规划可以解决此类问题,但用单源最短路径解决起来更简单。
为了避免d[i+1]<d[i]的情况发生,要检查 d[i]=min(d[i],d[i+1])。
题源来自《挑战程序竞赛》第二版110页。
//
// 110_layout.cpp
// changlle
//
// Created by user on 1/3/16.
// Copyright (c) 2016 user. All rights reserved.
//
#include <iostream>
#include <algorithm>
using namespace std;
int N=4;
int ML=2;
int MD=1;
int AL[2]={1,2}, BL[2]={3,4}, DL[2]={10,20};
int AD[1]={2}, BD[1]={3}, DD[1]={3};
const int inf=1000;
int d[4];
int main() {
fill(d,d+4,inf);
d[0]=0;
for (int k=0;k<N;k++) {
for (int i=0;i<N-1;i++)
if (d[i+1]<inf) d[i]=min(d[i],d[i+1]); // 总是有从i+1到i的权值为0
//由于按照顺序排列,所以d[i+1]必须<=d[i]
for (int i=0;i<ML;i++) {
if (d[AL[i]-1]<inf)
d[BL[i]-1]=min(d[BL[i]-1],d[AL[i]-1]+DL[i]);
}
for (int i=0;i<MD;i++) {
if (d[BD[i]-1]<inf)
d[AD[i]-1]=min(d[AD[i]-1],d[BD[i]-1]-DD[i]);
}
}
int res=d[N-1];
if (d[0]<0)
res=-1; //存在负圈,无解
cout<<res<<endl;
return 0;
}