poj1661 最短路

相当机智的一题,原本是放在DP专题里的题,思路一开始不是很清晰

看了网上dp解法后,感觉并不是很写的来

接着我开始想是否能暴力过去

于是很自然想到要构图,跑最短路了

每一层平台的左端点和右端点各自当做图中一个点

与其下方能到达的平台的左右端点相连

边权是高度差+水平差

建边时n^2暴力,起始点为0号点,地面为2*n+1号点

注意初始点连出去的边要单独处理

到地面的边要单独处理

Trick:可能直接落下到地面,要特判

建完后跑一遍迪杰斯特拉


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
struct data{
	int h,l,r;
}p[1010];
struct edge{
	int next,len,to;
}bian[101000];
struct node{
	int id,dis;
};
int T,n,X,Y,MAX;
int size=0,first[100100];
int dis[100010],exist[100010];
bool operator <(node a,node b)
{return a.dis>b.dis;}
bool comp(data x,data y)
{return x.h>y.h;}
void add(int x,int y,int z)
{
	size++;
	bian[size].next=first[x];
	first[x]=size;
	bian[size].to=y;
	bian[size].len=z;
}
void dijkstra(int s,int t)
{
	priority_queueq;
	dis[s]=0;
	q.push((node){s,0});
	while(!q.empty())
	{
		node t=q.top();
		q.pop();
		int u=t.id;
		if(exist[u])continue;
		exist[u]=1;
		dis[u]=t.dis;
		for(int i=first[u];i;i=bian[i].next)
		{
			if(dis[bian[i].to]>dis[u]+bian[i].len)
			{
				dis[bian[i].to]=dis[u]+bian[i].len;
				q.push((node){bian[i].to,dis[bian[i].to]});
			}
		}
	}
	printf("%d\n",dis[2*n+1]);
}
void addedge()
{
	for(int i=1;i<=n;i++)
	{
		int cnt1=0,cnt2=0;
		for(int j=i+1;j<=n;j++)
		{
			if(p[i].h-p[j].h>=0&&p[i].h-p[j].h<=MAX)
	     	{
				if(p[j].l<=p[i].l&&p[i].l<=p[j].r&&cnt1==0)
	     		{
					cnt1++;
					int ldis=p[i].h-p[j].h+p[i].l-p[j].l;
					add(i*2-1,j*2-1,ldis);
					int rdis=p[i].h-p[j].h+p[j].r-p[i].l;
					add(i*2-1,j*2,rdis);
				}
				if(p[j].l<=p[i].r&&p[i].r<=p[j].r&&cnt2==0) 
				{
                    cnt2++;
                    int ldis=p[i].h-p[j].h+p[i].r-p[j].l;
                    add(i*2,j*2-1,ldis);
                    int rdis=p[i].h-p[j].h+p[j].r-p[i].r;
                    add(i*2,j*2,rdis);
                }
			}
		}
		if(cnt1==0&&p[i].h<=MAX)
			add(i*2-1,2*n+1,p[i].h);
		if(cnt2==0&&p[i].h<=MAX)
			add(i*2,2*n+1,p[i].h);
	}
	int cnt=0;
	for(int i=1;i<=n;i++)
    if(p[i].l<=X&&X<=p[i].r&&Y-p[i].h>=0&&Y-p[i].h<=MAX&&cnt==0) 
	{
        cnt++;
        if(cnt==1) 
		{
            int ldis=Y-p[i].h+X-p[i].l;
            add(0,i*2-1,ldis);
            int rdis=Y-p[i].h+p[i].r-X;
            add(0,i*2,rdis);
        }
    }
    if(cnt==0)
        add(0,2*n+1,Y);
}
void clear()
{
	size=0;
	memset(first,0,sizeof(first));
	memset(dis,127,sizeof(dis));
	memset(exist,0,sizeof(exist));
}
int main()
{
	//freopen("in.in","r",stdin);
	scanf("%d",&T);	
	while(T--)
	{
		clear();
		scanf("%d%d%d%d",&n,&X,&Y,&MAX);
		for(int i=1;i<=n;i++)
			scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].h);
		sort(p+1,p+n+1,comp);
		addedge();
		dijkstra(0,2*n+1);
	}
}


你可能感兴趣的:(poj1661 最短路)