P1027 [NOIP 2001 提高组] Car 的旅行路线

题目描述

又到暑假了,住在城市 A 的 Car 想和朋友一起去城市旅游。
她知道每个城市都有 4 个飞机场,分别位于一个矩形的 4 个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第 i 个城市中高速铁路的单位里程价格为 Ti​,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为 t。

P1027 [NOIP 2001 提高组] Car 的旅行路线_第1张图片

注意:图中并没有标出所有的铁路与航线。

那么 Car 应如何安排到城市 B 的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。

找出一条从城市 A 到 B 的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。

输入格式

第一行为一个正整数 n,表示有 n 组测试数据。

每组的第一行有 4 个正整数 S,t,A,B。

S 表示城市的个数,t 表示飞机单位里程的价格,A,B 分别为城市A,B 的序号。

接下来有 S 行,其中第 i 行均有 7 个正整数xi1​,yi1​,xi2​,yi2​,xi3​,yi3​,Ti​,这当中的 (xi1​,yi1​),(xi2​,yi2​),(xi3​,yi3​),分别是第 i 个城市中任意 3 个机场的坐标,Ti​ 为第 i 个城市高速铁路单位里程的价格。

输出格式

共有 n 行,每行 1 个数据对应测试数据。
保留一位小数。

输入输出样例

输入 #1

1
3 10 1 3
1 1 1 3 3 1 30
2 5 7 4 5 2 1
8 6 8 8 11 6 3

输出 #1

47.5

说明/提示

【数据范围】
对于 100% 的数据,1≤n≤10,1≤S≤100,1≤A,B≤S。

【题目来源】

NOIP 2001 提高组第四题

参考代码:

#include
#define ll long long
using namespace std;
const ll N=4e5;
ll x[105][6],z[105],tot,y[105][6],h[N],ne[N],to[N];
double w[N],dp[N];
ll s,t,a,b,p;
bool vis[N];
void add(ll a,ll b,double c)
{
	tot++;
	ne[tot]=h[a];
	h[a]=tot;
	to[tot]=b;
	w[tot]=c;
}
void qiu(ll g,ll x1,ll x2,ll x3,ll y1,ll y2,ll y3)
{double x4,y4;x4=(x2+x3);y4=(y2+y3);x[g][4]=x4-x1;y[g][4]=y4-y1;}
void find(ll g)
{	ll x1,x2,x3,y1,y2,y3;
	x1=x[g][1];x2=x[g][2];x3=x[g][3];y1=y[g][1];y2=y[g][2];y3=y[g][3];
	if(y1==y2){if(x2==x3){x[g][4]=x1;y[g][4]=y3;return; }else {x[g][4]=x2;y[g][4]=y3;return; } }
	if(y1==y3){if(x2==x3){x[g][4]=x1;y[g][4]=y2;return; }else {	x[g][4]=x3;y[g][4]=y2;return; } }
	if(y2==y3){if(x1==x3){x[g][4]=x2;y[g][4]=y1;return;}else {x[g][4]=x3;y[g][4]=y1;return; } }
	if((y2-y1)*(y1-y3)/((x1-x3)*(x2-x1))==-1) qiu(g,x1,x2,x3,y1,y2,y3);
	if((y3-y2)*(y2-y1)/((x2-x1)*(x3-x2))==-1) qiu(g,x2,x1,x3,y2,y1,y3);
	if((y2-y3)*(y3-y1)/((x3-x1)*(x2-x3))==-1) qiu(g,x3,x2,x1,y3,y2,y1);
}
double dfs(ll a,ll b,ll c,ll d)
{
	ll x1,x2,y1,y2;x1=x[a][b];y1=y[a][b];x2=x[c][d];y2=y[c][d];
	return sqrt(abs(x1-x2)*abs(x1-x2)+abs(y1-y2)*abs(y1-y2));
}
void spfa(ll d,ll h1)
{
	memset(vis,0,sizeof(vis));
	for(ll i=5;i<=s*4+4;i++)
		dp[i]=0x7fffffff;
	dp[d*4+h1]=0.0;
	vis[d*4+h1]=1;
	queueq;
	q.push(d*4+h1);
	while(!q.empty())
	{
		ll j=q.front();q.pop();vis[j]=0;
		for(ll i=h[j];i;i=ne[i])
		{
			ll jj=to[i];
			if(dp[jj]>dp[j]+w[i])
			{
				dp[jj]=dp[j]+w[i];
				if(!vis[jj])
				{
					vis[jj]=1;
					q.push(jj);
				}
			}
		}
	}
}
int main()
{
	//ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	cin>>p;
	for(int i=1;i<=p;i++)
	{
		memset(h,0,sizeof(h));
		memset(ne,0,sizeof(ne));
		cin>>s>>t>>a>>b;
	for(ll i=1;i<=s;i++)
	{
		for(ll j=1;j<=3;j++)
			cin>>x[i][j]>>y[i][j];
		cin>>z[i];
		find(i);
	}
	for(ll i=1;i<=s;i++)
		for(ll k=1;k<=4;k++)
		{
			for(ll j=1;j<=k-1;j++)
				add(4*i+k,4*i+j,dfs(i,k,i,j)*1.0*z[i]);
			for(ll j=k+1;j<=4;j++)
				add(4*i+k,4*i+j,dfs(i,k,i,j)*1.0*z[i]);
		}
	for(ll i=1;i<=s;i++)
		for(ll k=1;k<=4;k++)
		for(ll r=1;r<=4;r++)
		{
			for(ll j=1;j<=i-1;j++)
				add(4*i+k,4*j+r,dfs(i,k,j,r)*1.0*t);
			for(ll j=i+1;j<=s;j++)
				add(4*i+k,4*j+r,dfs(i,k,j,r)*1.0*t);
		}
	double minn=0x7fffffff;
	for(ll i=1;i<=4;i++)
	{
		spfa(a,i);
		for(ll j=1;j<=4;j++)
			minn=min(minn,dp[b*4+j]);
	}
	printf("%0.1lf",minn);
	}
	
	return 0;
}

你可能感兴趣的:(c++,算法,spfa)