zoukankan      html  css  js  c++  java
  • 洛谷 P2747 Canada Tour 周游加拿大 动态规划

    Description

    你赢得了一场航空公司举办的比赛,奖品是一张加拿大机票。旅行在这家航空公司开放的最西边的城市开始,然后一直自西向东旅行,直到你到达最东边的城市,再由东向西返回,直到你回到开始的城市。每个城市只能访问一次,除了旅行开始的城市之外,这个城市必定要被访问两次(在旅行的开始和结束)。你不允许使用其他公司的航线或者用其他的交通工具。

    给出这个航空公司开放的城市的列表,和两两城市之间的直达航线列表。找出能够访问尽可能多的城市的路线,这条路线必须满足上述条件,也就是从列表中的第一个城市开始旅行,访问到列表中最后一个城市之后再返回第一个城市。

    Input

    Line 1: 航空公司开放的城市数 N 和将要列出的直达航线的数量 V。N 是一个不大于 100 的正整数。V 是任意的正整数。

    Lines 2..N+1: 每行包括一个航空公司开放的城市名称。城市名称按照自西向东排列。不会出现两个城市在同一条经线上的情况。每个城市的名称都是一个字符串,最多15字节,由拉丁字母表上的字母组成;城市名称中没有空格。

    Lines N+2...N+2+V-1:每行包括两个城市名称(由上面列表中的城市名称组成),用一个空格分开,这样就表示两个城市之间的直达双程航线。

    Ouput

    Line 1: 按照最佳路线访问的不同城市的数量 M。如果无法找到路线,输出 1。

    Sample Input

    8 9
    Vancouver
    Yellowknife
    Edmonton
    Calgary
    Winnipeg
    Toronto
    Montreal
    Halifax
    Vancouver Edmonton
    Vancouver Calgary
    Calgary Winnipeg
    Winnipeg Toronto
    Toronto Halifax
    Montreal Halifax
    Edmonton Montreal
    Edmonton Yellowknife
    Edmonton Calgary

    Sample Output

    7

    HINT

    样例解释: Vancouver, Edmonton, Montreal, Halifax, Toronto, Winnipeg, Calgary, 和 Vancouver (回到开始城市,但是不算在不同城市之内)。

    Solution

    看起来很像一道费用流的题,但仔细思考一下我们不难发现动态规划便可以轻松解决,本题也可以通过floyd求最大环来解决。这里主要介绍动态规划的方法。

    类似floyd,我们采用邻接表的方式建图,由于需要建立城市与数字之间的映射关系从而建图,大佬们一般用的是map,本蒟蒻不会那么高级的函数,采用暴力循环的方式。

    由于要求路径不重复,我们可以把所求的路径分成两段,即从起点出发与回到起点的两条路径,那么假设有两个人分别走这两条路径,从而想出我们的状态:f[i][j]表示一个人到达i,另一个人到达j的状态数。状态转移方程可容易推得:

    f[i][j]=max(f[i][k]+1)+1(k,j有航线且1<=k<j且f[i][k]>0)

    Code

    #include <stdio.h>
    #include <algorithm>
    #include <string.h>
    #define N 110
    using namespace std;
    int f[N][N],map[N][N];
    int n,v;
    int ans=1;
    char a[N],b[N];
    void add(int x,int y){map[x][y]=1;map[y][x]=1;}
    struct note 
    {
        int num;
        char id[20];
    }city[N];
    void floyd()
    {
        f[1][1]=1;
        for(int i=1;i<n;i++)
            for(int j=i+1;j<=n;j++)
                for(int k=1;k<j;k++)
                    if(map[j][k]&&f[i][k]&&f[i][k]+1>f[i][j])
                        f[i][j]=f[j][i]=f[i][k]+1;
         for(int i=1;i<=n;i++)
            if(map[i][n])
                ans=max(ans,f[i][n]);
    }
    int main()
    {
        scanf("%d%d",&n,&v);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",city[i].id+1);
            city[i].num=i;
        }
        for(int i=1;i<=v;i++)
        {
            scanf("%s",a+1);
            scanf("%s",b+1);
            int x,y;
            for(int j=1;j<=n;j++)
            {
                if(strcmp(a+1,city[j].id+1)==0)
                    x=city[j].num;
                if(strcmp(b+1,city[j].id+1)==0)
                    y=city[j].num;
            }
            add(x,y);
        }
        floyd();
        printf("%d",ans);
    }
  • 相关阅读:
    设计模式之工厂模式-抽象工厂(02)
    1036 跟奥巴马一起编程 (15 分)
    1034 有理数四则运算 (20 分)
    1033 旧键盘打字 (20 分)
    1031 查验身份证 (15 分)
    大学排名定向爬虫
    1030 完美数列 (25 分)二分
    1029 旧键盘 (20 分)
    1028 人口普查 (20 分)
    1026 程序运行时间 (15 分)四舍五入
  • 原文地址:https://www.cnblogs.com/kanbokedeshiwoerzi/p/8987181.html
Copyright © 2011-2022 走看看