(纪中)2156. 复仇者vsX战警之训练(train)【SPFA】

天涯浪子 提交于 2020-02-12 12:10:34

(File IO): input:attack.in output:attack.out
时间限制: 1000 ms 空间限制: 262144 KB 具体限制
Goto ProblemSet


题目描述
月球上反凤凰装甲在凤凰之力附身霍普之前,将凤凰之力打成五份,分别附身在X战警五大战力上面辐射眼、白皇后、钢力士、秘客和纳摩上(好尴尬,汗)。
在凤凰五使徒的至高的力量的威胁下,复仇者被迫逃到昆仑的一座山上,因为凤凰五使徒监视不到那里。
霍普加入了复仇者,为了磨练自己,她在nn个山峰之间跳跃。
nn个山峰在一条直线上,每个山峰都有不同的高度,只知道这些山峰在水平上相对位置。霍普可以将这些山峰左右移动但不能改变他们的相对位置(要保证两两山峰间距为整数且大于等于11)。霍普要从最矮的山峰开始跳,每次跳向第一个比现在她所在的山峰高的山峰,一共跳n1n-1次,由于能力有限,每次跳跃的水平距离小于等于dd
霍普想知道如何移动这些山峰,使得在可以经过所有的山峰并跳到最高的山峰上的基础下,又要使最矮的山峰和最高的山峰的水平距离最远,霍普要你求出最远的水平距离。如果无论如何也不能经过所有的山峰并跳到最高的山峰上,那么输出1-1


输入
输入文件名为attack.inattack.in
本题每个测试点有多组数据,
在第一行中有一个整数tt,表示数据的数目t<=500(t<=500)
对于每组数据:
第一行包含两个整数n1n1000n(1≤n≤1000)d1d1000000d(1≤d≤1000000)
下一行包含nn个整数,给出nn个山峰的高度,输入顺序即为山峰在水平上的相对顺序。在每个数据中,所有的高度都是唯一的。

输出
输出文件名为attack.outattack.out
输出共t行。
对于每组数据输出最远的水平距离。如果无论如何也不能经过所有的山峰并跳到最高的山峰上,那么输出1-1


样例输入
3
4 4
20 30 10 40
5 6
20 34 54 10 15
4 2
10 20 16 13

样例输出
3
3
-1


数据范围限制
【数据说明】
对于100%的数据,1≤n≤1000,1≤d≤1000000


解题思路
思路:最短路(SPFASPFA)+排序
1、两个山峰之间水平距离至少为11(因为山峰不能再同一位置上)。
2、霍普每次最多跳dd的水平距离。
对于第一个条件,对于两个相邻的山峰,相对位置(即输入顺序)大的向相对位置小的连一条1-1的边。
对于第二个条件,对于两个高度排名相邻的山峰,相对位置小的向相对位置大的连一条dd的边。
然后比较最高和最低的山峰,从相对位置小的那个山峰出发,跑一遍SPFASPFA最短路,输出到相对位置大的山峰的距离。


代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cmath>
using namespace std;
long long head[10000],dis[1010],v[1010],st[10000010],qq[2000];
int t,n,d,len,he,ta,aa;
struct c {
   int x,y;
}a[10000];
struct cc {
   int x,y,z;
}b[10000];
void add(int x,int y,int z)
{
   b[++len].x=y;
   b[len].y=z;
   b[len].z=head[x];
   head[x]=len;
}
bool cmp(const c&l,const c&r)
{
   return l.x<r.x;
}
void spfa()
{
   memset(dis,127,sizeof(dis));
   memset(v,0,sizeof(v));
   memset(qq,0,sizeof(qq));
   he=0,ta=1;
   if(a[1].y<a[n].y)aa=1;
   else aa=n;
   st[1]=a[aa].y;
   dis[a[aa].y]=0;
   v[a[aa].y]=1;
   qq[a[aa].y]=1;
   while(he<=ta) {
       he++;
       int x=st[he];
       for(int i=head[x]; i; i=b[i].z) {
           if(dis[b[i].x]>dis[x]+b[i].y) {
               dis[b[i].x]=dis[x]+b[i].y;
               qq[b[i].x]++;
               if(qq[b[i].x]<1000)
                   if(!v[b[i].x]) {
                       ++ta;
                       v[b[i].x]=1;
                       st[ta]=b[i].x;
                   }
           }
       }
       v[x]=0;
   }
}
int main()
{
   freopen("attack.in","r",stdin);
   freopen("attack.out","w",stdout);
   scanf("%d",&t);
   for(int i=1; i<=t; i++) {
       memset(head,0,sizeof(head));
       memset(b,0,sizeof(b));
       len=0;
       memset(a,0,sizeof(a));
       scanf("%d%d",&n,&d);
       for(int i=1; i<=n; i++) {
           scanf("%d",&a[i].x);
           a[i].y=i;
           if(i!=1)add(i,i-1,-1);
       }
       sort(a+1,a+n+1,cmp);
       for(int i=2; i<=n; i++)
       if(a[i].y<a[i-1].y) add(a[i].y,a[i-1].y,d);
       else add(a[i-1].y,a[i].y,d);
       spfa();
       aa=n+1-aa;
       if(dis[a[aa].y]<=0)printf("-1\n");
       else
       printf("%d\n",dis[a[aa].y]);
   }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!