SPOJ PUTNIK dp

本文探讨了一种特殊的旅行商问题,其中旅行商需访问N个城市且满足特定序列约束。文章提供了一个高效的算法解决方案,通过动态规划计算最优路径,确保满足条件的同时实现最短总飞行时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PUTNIK - Putnik


Chances are that you have probably already heard of the travelling salesman problem. If you have, then you are aware that it is an NP-hard problem because it lacks an efficient solution. Well, this task is an uncommon version of the famous problem! Its uncommonness derives from the fact that this version is, actually, solvable efficiently. 


The travelling salesman is on a mission to visit N cities, each exactly once. The cities are represented by numbers 1, 2, ..., N. What we know is the direct flight duration between each pair of cities. The salesman, being the efficient man that he is, wants to modify the city visiting sequence so that the total flight duration is the minimum possible. 

Alas, all is not so simple. In addition, the salesman has a peculiar condition regarding the sequence. For each city labeled K must apply: either all cities with labels smaller than K have been visited before the city labeled K or they will all be visited after the city labeled K. In other words, the situation when one of such cities is visited before, and the other after is not allowed. 

Assist the poor fellow in his ambitious mission and calculate the minimum total flight duration needed in order to travel to all the cities, starting from whichever and ending in whichever city, visiting every city exactly once, so that his peculiar request is fulfilled. 


Input

The first line of input contains the positive integer N (2 ≤ N ≤ 1500), the number of cities. Each of the following N lines contains N positive integers from the interval [0, 1000]. The number in Bth place in the Athrow represents the flight duration between cities A and B; that number is equal to the Ath number in the Bthrow. When A = B, that number is 0. Otherwise, it is a positive value.


Output

The first and only line of output must contain the required minimum total flight duration. 


Example

Input:
3 
0 5 2 
5 0 4 
2 4 0 

Output:
7

Input:
4 
0 15 7 8 
15 0 16 9 
7 16 0 12 
8 9 12 0
Output:
31

Clarification of the first example:
the optimal sequence is 2, 1, 3 or 3, 1, 2. The sequence 1, 3, 2 is even more favorable, but it does not fulfill the salesman's condition.

Clarification of the second example:
the sequence is either 3, 1, 2, 4 or 4, 2, 1, 3.


题意:旅行商的目的是走完N个城市,每个城市仅走一次。城市标号1,2.....N。
每两个城市之间有一条边,对应一个边权。求出一个旅行的序列,使得权值和最小。
旅行商对旅行有着特殊的要求,对于一个标号K的城市,所有标号小于K的要么在游览K之前被游览完,要么只能在游览完K之后才能被游览。
旅行可以从任意城市开始和终止。


题解:定义dp[i][j]为i为起点,j为终点的旅程的最小值。

dp[i][j]=dp[i-1][j]+dis[i][i-1];
dp[i][i-1]=min(dp[i][i-1],dp[i-1][j]+dis[i][j]);

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int dp[1505][1505],dis[1505][1505];
int main(){
	int n,i,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		for(j=1;j<=n;j++)scanf("%d",&dis[i][j]);
	}
	memset(dp,127,sizeof(dp));
	dp[2][1]=dis[1][2];
	for(i=3;i<=n;i++){
		for(j=1;j<=i-2;j++){
			dp[i][j]=dp[i-1][j]+dis[i][i-1];
			dp[i][i-1]=min(dp[i][i-1],dp[i-1][j]+dis[i][j]);
		}
	}
	int ans=1<<30;
	for(i=1;i<n;i++)ans=min(ans,dp[n][i]);
	printf("%d\n",ans);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值