1.x的旅行

  (travel.pas/c/cpp)

【问题描述】

    小x大学毕业后,进入了某个公司做了高层管理,他每年的任务就是检查这个公司在全国各地N个分公司的各种状况,每个公司都要检查一遍,且只能检查一遍,也就是说这N个地方只能也必须去一次。

当然,小x每年可以选择从任意一个城市开始,任意一个城市结束。

现在给出这N个公司所在地任意两个地点飞机票的价格,现在小x为了给公司省下交通费,需要设计一个程序,来计算一下如何花费最低能够完成任务。

作为一名有过信息学竞赛经历的有志青年,小x给自己的路线又规定了一个约束条件:如果要访问编号为K的城市,那么编号比K小的所有城市或者在访问K之前访问,或者在访问K之后访问。这个条件也必须遵守。

比如:如果有3个城市:2 1 3和 3 1 2 的顺序都是合法的,但是 1 3 2的顺序就是非法的,因为比3小的1在3之前,2在3之后,和小x的要求冲突。

【输入】

第一行:一个整数N。

接下来N行,每行N个整数。第i行第j列的值a[i][j]表示第i个城市到第j个城市飞机票的价格。保证这N个整数在[0..1000]之间。

【输出】

一个整数,表示满足要求的最小花费。

 

【输入输出样例1】

travel.in

travel.out

3

0 5 2

5 0 4

2 4 0

7

 

【输入输出样例2】

travel.in

travel.out

4

0 15 7 8

15 0 16 9

7 16 0 12

8 9 12 0

31

【样例解释】顺序为3, 1, 2, 4 或者 4, 2, 1, 3.

【数据范围】

   30% 数据保证N<=10

   50% 数据保证 N<=20

   100% 数据保证 N<=1500

 

思路:

第一反应是dfs,但是如何判断是否符合题意呢?(反正我不会)。

仔细想想,点1不在中间,就在对头或队尾。那我们从1枚举到n分别放在上一次l,r的两边不就行了。

代码也不长。

Here is it;

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<string>
 7 #include<iomanip>
 8 #include<ctime>
 9 #include<queue>
10 #include<algorithm>
11 using namespace std;
12 const int maxn=5000001;
13 int n,a[2000][2000];
14 int f[2000][2000];
15 int ans=maxn;
16 
17 int dfs(int l,int r)
18 {
19     if(f[l][r]) return f[l][r];
20     int next=max(l,r)+1;
21     if(next==n+1)
22     {
23         return 0;
24     }
25     return f[l][r]=min(a[next][l]+dfs(next,r),a[r][next]+dfs(l,next));
26 }
27 
28 int main()
29 {
30     freopen("travel.in","r",stdin);
31     freopen("travel.out","w",stdout);
32     ios::sync_with_stdio(false);
33     cin>>n;
34     for(int i=1;i<=n;i++)
35         for(int j=1;j<=n;j++)
36             cin>>a[i][j];
37     for(int i=1;i<=n;i++)
38     {
39         dfs(1,1);
40     }
41     cout<<f[1][1]<<endl;
42     return 0;
43 }