zoukankan      html  css  js  c++  java
  • 竞码编程-蓝桥杯模拟赛4-D题

    这道题目算法很简单,但是实现代码比较困难。下面是关于该题目的讲解。

    首先这是一个填空题,只需要结果,因为在编码时对代码的优化不需要太过于关注。只要保证算法能够在可承受的时间范围内处理数据即可。

    关于官方给出的讲解中,利用dfs嵌套dfs来寻路,这实在时有些困难。这不仅需要每次对已经完成的路径进行记录、比较,而且嵌套dfs本身就需要更加严谨的结构。

    这里我采用的思路是:dfs找到所有的路,并将该路径对应的权值、路径经过的点、路径的长度记录下来。在记录路径经过的点时,由于后期比较中不再关注路径所经过点的顺序,而只关心路径经过的点是哪些,所以这时对点的编号进行排序,方便后期的比较。这种方法下,我得到了1432条路。然后对所有的路径按照权值和进行排列。然后去重。最后对相同权值的路径进行比较以得到答案273.

    代码如下:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<vector>
      6 #include<string>
      7 #include<algorithm>
      8 using namespace std;
      9 
     10 struct road
     11 {
     12     int lenth;//路的长度 
     13     int value;//权值和 
     14     int list[17];//途径结点 
     15     bool operator < (const road& rhs) const
     16     {
     17         return value < rhs.value;
     18     }
     19 };
     20 
     21 road allway[3200];//这个大小需要后期运行时尝试 
     22 int cur=0;
     23 vector<int> ver[16];//路信息 
     24 int pv[]={1,3,2,2,4,2,4,4,7,3,5,6,3,1,5,2};
     25 //保存权值 
     26 int vis[16];
     27 
     28 int readin()
     29 {
     30     for(int i=0;i<18;i++)
     31     {
     32         int a,b;
     33         cin>>a>>b;
     34         ver[a].push_back(b);
     35         ver[b].push_back(a);
     36     }//借助vector数组实现无向图 
     37     return 0;
     38 }
     39 
     40 int w[17];//dfs的路径记录数组 
     41 int dfs(int nowpoint,int nowvalue,int step)
     42 {
     43     if(step==15)return 0;
     44     //可以采用一笔画的方式估计出最长的路径大约是14 
     45     if(1)//这里发现路径长度可以为1,原题并没有说明 
     46     {
     47         allway[cur].lenth=step+1;
     48         allway[cur].value=nowvalue;
     49         memset(allway[cur].list,0,sizeof(int)*17);
     50         memcpy(allway[cur].list,w,sizeof(int)*allway[cur].lenth);
     51         sort(allway[cur].list,allway[cur].list+step+1);
     52         //路径规范化 
     53         cur++;
     54     }
     55     //储存计算出的路 
     56     for(int i=0;i<ver[nowpoint].size();i++)
     57     {
     58         int next=ver[nowpoint][i];
     59         if(vis[next])continue;
     60         vis[next]=1;
     61         w[step+1]=next;//记录路径 
     62         dfs(next,nowvalue+pv[next],step+1);
     63         w[step+1]=0;//消除路径记录 
     64         vis[next]=0;
     65     }//
     66     return 0;
     67 }
     68 
     69 int initial()
     70 {
     71     freopen("input.txt","r",stdin);
     72     readin();
     73     cout<<"READ-OK"<<endl; 
     74     //路径数据读取完毕 
     75     cur=0;
     76     for(int i=0;i<16;i++)
     77     {
     78         memset(vis,0,sizeof(vis));
     79         memset(w,0,sizeof(w));
     80         w[0]=i;
     81         vis[i]=1;
     82         dfs(i,pv[i],0);
     83     }//找出所有的路径 
     84     sort(allway,allway+cur);
     85     //按照权值和进行排序
     86     //根据后面的去重代码,这句代码其实也没什么必要
     87     cout<<"SORT-OK"<<endl;
     88     return 0;
     89 }
     90 
     91 bool same(road& p1,road& p2)//比较函数 
     92 {
     93     if(p1.value!=p2.value)return false;
     94     if(p1.lenth!=p2.lenth)return false;
     95     for(int i=0;i<p1.lenth;i++)
     96     {
     97         if(p1.list[i]!=p2.list[i])return false;
     98     }
     99     return true;
    100 }
    101 
    102 int psort()
    103 {
    104     initial();
    105     cout<<cur<<endl;
    106     //
    107     int num=cur;
    108     for(int i=0;i<cur;i++)
    109     {
    110         if(allway[i].value==1000)continue;
    111         for(int k=i+1;k<cur;k++)
    112         {
    113             if(allway[k].value==1000)continue;
    114             if(same(allway[i],allway[k]))
    115             {
    116                 allway[k].value=1000;
    117                 /*C++中对去重的实现方式是将重复的元素放在数组的最后,
    118                 这里采用那种思想,将重复元素的value的值设置为一个很大的1000
    119                 然后在最后进行排序,使得所有重复的元素排列到数组最后
    120                 剩余的前num个路径就是非重复路径*/
    121                 num--;
    122             }
    123         }
    124     }//这里的算法可以再优化,不过没什么必要,计算本身很快 
    125     sort(allway,allway+cur);
    126     return num; 
    127 }
    128 
    129 int ismakepair(road& p1,road& p2)//验证是否可以组成答案 
    130 {
    131     for(int i=0;i<p1.lenth;i++)
    132     {
    133         int s=p1.list[i];
    134         for(int k=0;k<p2.lenth;k++)
    135         {
    136             if(s==p2.list[k])return 0;
    137         }
    138     }
    139     return 1;
    140 }
    141 
    142 int main()
    143 {
    144     int num=psort();
    145     int ans=0;
    146     for(int i=0;i<num;i++)
    147     {
    148         for(int k=i+1;k<num;k++)
    149         {
    150             if(allway[i].value!=allway[k].value)continue;
    151             if(ismakepair(allway[i],allway[k]))ans++;
    152         }
    153     }
    154     cout<<ans<<endl;
    155     return 0;
    156 }

    input.txt文件:

    0 2
    2 1
    2 3
    1 5
    3 7
    5 4
    5 6
    7 6
    7 8
    4 10
    6 12
    8 14
    10 9
    10 11
    12 11
    12 13
    14 13
    14 15

    OK

  • 相关阅读:
    存储引擎的优缺点及增删改查基本操作
    安装Mariadb
    Mysql 入门概念
    Nginx语法着色
    find用法,文件压缩和lsof和cpio
    软件包管理
    Django 生成六位随机图片验证码
    Django自定义过滤器和自定义标签
    Django零碎知识点
    jQuery实现淡入淡出样式轮播
  • 原文地址:https://www.cnblogs.com/savennist/p/12602180.html
Copyright © 2011-2022 走看看