就是一个忍者,要从最矮的树,依次跳过N-1颗到最高的树,一次跳跃水平距离不得超过D,现在给了所有树的高度,以及他们的相对位置,问如何摆树,让最高树和最矮树距离最大。
思路:
差分约束系统,设dis[i]表示树i的距离,这里的不等式有如下:
①首先树不要按高度排序,两两之间坐标不可重合,且保持相对位置。
②然后树按高度排序,两两之间距离不可超过D。
然后 最高树在最矮树的左边或右边 两种情况不太一样,我这里是一个求得是最长路,一个是最短路。
#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<vector>
using namespace std;
const int maxn=1200;
int n,d;
struct tr
{
int id;
int h;
bool operator < (tr tar) const
{
if(tar.h>h) return true;
return false;
}
};
struct Edge
{
int from;
int to;
int w;
};
vector<tr> tree;
vector<Edge> E;
int dis[1200];
void init()
{
tree.clear();
E.clear();
}
bool Bellman_ford()
{
memset(dis,0x3f,sizeof(dis));
dis[tree[0].id]=0;
int size=E.size();
bool type=0;
//???????????
if(tree[0].id>tree[n-1].id)
{
type=1;
for(int i=0;i<size;i++)
{
swap(E[i].from,E[i].to);
E[i].w=-E[i].w;//???????????????????
E[i].w=-E[i].w;
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<size;j++)
{
int from=E[j].from;
int to=E[j].to;
int w=E[j].w;
if(dis[to]>dis[from]+w) dis[to]=dis[from]+w;
}
}
for(int j=0;j<size;j++)
{
int from=E[j].from;
int to=E[j].to;
int w=E[j].w;
if(dis[to]>dis[from]+w)
{
return false;
}
}
return true;
}
int main()
{
while(cin>>n>>d)
{
if(n==0 && d==0) break;
init();
for(int i=0;i<n;i++)
{
int h;scanf("%d",&h);
tr tmp;
tmp.id=i;
tmp.h=h;
tree.push_back(tmp);
}
int size=tree.size();
for(int i=0;i<size-1;i++)
{
Edge tmp;
tmp.from=i+1;
tmp.to=i;
tmp.w=-1;
E.push_back(tmp);
}
sort(tree.begin(),tree.end());
for(int i=0;i<size-1;i++)
{
if(tree[i].id < tree[i+1].id)
{
Edge tmp;
tmp.from=tree[i].id;
tmp.to=tree[i+1].id;
tmp.w=d;
E.push_back(tmp);
}
else
{
Edge tmp;
tmp.from=tree[i+1].id;
tmp.to=tree[i].id;
tmp.w=d;
E.push_back(tmp);
}
}
bool has=Bellman_ford();
if(has==false)
{
printf("-1\n");
continue;
}
printf("%d\n",abs(dis[tree[n-1].id]) );
}
return 0;
}