竞码编程-蓝桥杯模拟赛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

原文地址:https://www.cnblogs.com/savennist/p/12602180.html