A Portal 2020牛客暑期多校训练营(第五场)

https://ac.nowcoder.com/acm/contest/5670/A

把一个任务分为两个任务,先到ai再到bi

设dp[i][u]为完成了i任务后,在u位置放了一个传送门的最小距离

那么有dp[i+1]四种转移方法,直接由a[i]走到a[i+1],由a[i]瞬移到u再走到a[i+1],先走到v然后瞬移回u再走到a[i+1]并把传送门放在v,由a[i]传送到u然后走到v再走到a[i+1]。

#include
using namespace std;
typedef pair p;
typedef long long ll;
const int maxl=610;
const ll inf=1ll<<60;
int n,m,k;ll ans;
int a[maxl],b[maxl];
int frm[maxl][maxl];
ll f[maxl][maxl];
ll dp[maxl][maxl];
bool in[maxl];

inline void prework()
{
	scanf("%d%d%d",&n,&m,&k);
	int u,v,w;
	memset(f,0x3f,sizeof(f)); 
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		f[u][v]=min(f[u][v],1ll*w);
		f[v][u]=min(f[v][u],1ll*w);
	}
	for(int i=1;i<=2*k;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
		f[i][i]=0;
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}

inline void mainwork()
{
	memset(dp,0x3f,sizeof(dp));
	dp[0][1]=0;a[0]=1;
	for(int i=0;i<2*k;i++)
		for(int u=1;u<=n;u++)
		{
			dp[i+1][u]=min(dp[i+1][u],dp[i][u]+f[a[i]][a[i+1]]);
			dp[i+1][u]=min(dp[i+1][u],dp[i][u]+f[u][a[i+1]]);
			for(int v=1;v<=n;v++)
			{
				dp[i+1][v]=min(dp[i+1][v],dp[i][u]+f[a[i]][v]+f[u][a[i+1]]);
				dp[i+1][v]=min(dp[i+1][v],dp[i][u]+f[u][v]+f[v][a[i+1]]);
			}
		}
	ans=dp[2*k][1];
	for(int i=1;i<=n;i++)
		ans=min(ans,dp[2*k][i]);
}

inline void print()
{
	printf("%lld\n",ans);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

你可能感兴趣的:(DP,图上DP)