您的位置:首页 > 其它

PTA天梯决赛14题直捣黄龙

2017-03-23 13:53 190 查看
题目:

5-14 直捣黄龙   (30分)

本题是一部战争大片 —— 你需要从己方大本营出发,一路攻城略地杀到敌方大本营。首先时间就是生命,所以你必须选择合适的路径,以最快的速度占领敌方大本营。当这样的路径不唯一时,要求选择可以沿途解放最多城镇的路径。若这样的路径也不唯一,则选择可以有效杀伤最多敌军的路径。

输入格式:

输入第一行给出2个正整数
N
(2 ≤\le≤
N

≤\le≤
200,城镇总数)和
K
(城镇间道路条数),以及己方大本营和敌方大本营的代号。随后
N
-1行,每行给出除了己方大本营外的一个城镇的代号和驻守的敌军数量,其间以空格分隔。再后面有
K
行,每行按格式
城镇1 城镇2 距离
给出两个城镇之间道路的长度。这里设每个城镇(包括双方大本营)的代号是由3个大写英文字母组成的字符串。

输出格式:

按照题目要求找到最合适的进攻路径(题目保证速度最快、解放最多、杀伤最强的路径是唯一的),并在第一行按照格式
己方大本营->城镇1->...->敌方大本营
输出。第二行顺序输出最快进攻路径的条数、最短进攻距离、歼敌总数,其间以1个空格分隔,行首尾不得有多余空格。

输入样例:

10 12 PAT DBY
DBY 100
PTA 20
PDS 90
PMS 40
TAP 50
ATP 200
LNN 80
LAO 30
LON 70
PAT PTA 10
PAT PMS 10
PAT ATP 20
PAT LNN 10
LNN LAO 10
LAO LON 10
LON DBY 10
PMS TAP 10
TAP DBY 10
DBY PDS 10
PDS PTA 10
DBY ATP 10

输出样例:

PAT->PTA->PDS->DBY
3 30 210


简要分析:这个题目个人感觉就是枚举各种路线的走法,然后把满足条件的路线和最优路线给记录下来,说起来好像很简单(笑哭)确实对大牛来说也是很简单的,可是作为一只萌新,我可花了不少时间呐,唉,好了不闲聊了,讲正事。

思路:由于要考虑每一条路线,即把每一条路线都给走一遍,所以我们需要回溯(我只能想到这种办法TAT)还有图。主要思路理清了这题也不是特别难,总共就两个思想嘛(写了那么久还好意思说),接下来呈上代码,有可以优化的建议的话请大佬们提出呦。

代码:

#include<stdio.h>

#include<stdlib.h>

struct cityi            //城市数据

{

    int arrive_;        //可以进入的城市的数目

    struct a                

    {

       int cityid;            //可以进入的城市

       int distance;        //去这个城市所需要的距离

    }arrive[199+20];    //由于城市上限不超过200个,所以我们就算所有城市都能去也只有199条路。

    int enemy;

}citys[199+20];            //同上,不超过200个城市。

int symbol[201]={0};    //标记,如果走过的城市在同一条路线里不会走第二次,因为我们要最快速度最短距离。

int rails=0;            //最短距离的路的条数。

int railway[201];        //记录路线

int truerailway[201];    //最终最优路线

int railway_=0;            //当前经过的城市的个数

int truerailways=-1;    //最优路线经过城市的个数

char cityname[201][4];    //代号转换,将名字转换成数字,后面的conversion函数就是转换功能。

int maxkill=-1;            //最优路线歼敌数

int mixdistance=500000;    //最短进攻距离

int maxtown=-1;            //最优路线解放的城镇的数目

int conversion(char name[4],int N);        //城镇代号与数字之间的转化

int compare(char name1[4],char name2[4]);  //比较城镇是否相同

void seek(int  now ,int distance,int kill,int town);

int main()            

{

     int N,K;

     char wgzf;

     int amount;

     scanf("%d%d",&N,&K);

     scanf("%c",&wgzf);

     scanf("%s",cityname[0]);

     scanf("%s",cityname[1]);

     citys[0].arrive_=0;                //初始化第一个城镇(即我方大本营)

     citys[0].enemy=0;                    //我方大本营没有敌军

     amount=N-1;                        //题目要求N-1条路线

     int cityname_=2;                    //已经初始化了两个城镇,所以从第三个城镇开始计数

     while(amount--)                        //输入,并初始化所有城镇注意由于先前只输入一个敌方大本营,并没有输入敌人人数。

     {

         int number;

        scanf("%s",cityname[cityname_]);

        scanf("%d",&number);

        if(compare(cityname[1],cityname[cityname_]))    //判断是否为敌方大本营,是的话初始化敌人个数

        {

            citys
b1b3
[1].enemy=number;

            citys[1].arrive_=0;

        }

        else

        {

            citys[cityname_].enemy=number;

            citys[cityname_].arrive_=0;

            cityname_++;

        }

     }

     while(K--)                                //输入路线以及距离(注意两个城镇都要初始化)

     {

         char name1[4];                        

         char name2[4];

         int distance;

         scanf("%s",name1);

         scanf("%s",name2);

         scanf("%d",&distance);

         int id1,id2;

         id1=conversion(name1,N);

         id2=conversion(name2,N);

         citys[id1].arrive[citys[id1].arrive_].cityid=id2;

         citys[id1].arrive[citys[id1].arrive_++].distance=distance;

         citys[id2].arrive[citys[id2].arrive_].cityid=id1;

         citys[id2].arrive[citys[id2].arrive_++].distance=distance;

    

     }

    

     int times;            //标记大本营

     symbol[0]=1;

     seek(0,0,0,0);

    int hh;

    printf("%s",cityname[0]);

    for(hh=0;hh<truerailways;hh++)

        printf("->%s",cityname[truerailway[hh]]);

    printf("\n");

    printf("%d %d %d",rails,mixdistance,maxkill);

}

int compare(char name1[4],char name2[4])        //比较函数

{

    char *p1,*p2;

    p1=name1;

    p2=name2;

    while(*p1==*p2 && *p1!='\0')

    {

        p1++;

        p2++;

    }

     if(*p1=='\0')

         return 1;

     else

         return 0;

}

int conversion(char name[4],int N)            //转换函数,转换城镇代号

{

     int i;

     for(i=0;i<N;i++)

         if(compare(cityname[i],name))

            return i;

     return -1;

}

void seek(int now ,int distance,int kill,int town)        //查询函数,枚举回溯每一条路线

{

    kill+=citys[now].enemy;

    if(now==1)                                            //终止条件,由于先前定义地方大本营位置为1

    {

        if(distance<=mixdistance)                        //是最短距离的时候进行考虑否则直接跳过

        {

            if(distance<mixdistance)

            {

                rails=0;                                //若是新的最短距离,更新最优路线数量

                mixdistance=distance;

                maxtown=town;

                maxkill=kill;

                truerailways=railway_;

                int times;

                for(times=0;times<railway_;times++)            //记录最优路线

                    truerailway[times]=railway[times];

            }

            else

                if(town>=maxtown)

                {

                    if(town>maxtown)

                    {

                        maxtown=town;

                        maxkill=kill;

                        truerailways=railway_;

                        int times;

                        for(times=0;times<railway_;times++)        //记录最优路线

                            truerailway[times]=railway[times];

                    }

                    else

                    if(kill>maxkill)

                    {

                        maxkill=kill;

                        truerailways=railway_;

                        int times;

                        for(times=0;times<railway_;times++)        //记录最优路线

                            truerailway[times]=railway[times];

                    }

                }

                rails++;

        }

        return ;

    }

    int i;

    for(i=0;i<citys[now].arrive_;i++)                //回溯

    {

        if(symbol[citys[now].arrive[i].cityid]==0)        //判断是否已被标记

        {

            railway[railway_++]=citys[now].arrive[i].cityid;    //记录当前路线

            symbol[citys[now].arrive[i].cityid]=1;

            seek(citys[now].arrive[i].cityid,distance+citys[now].arrive[i].distance,kill,town+1);

            symbol[citys[now].arrive[i].cityid]=0;            //

            railway_--;                                        //返回初始状态

        }

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: