问题描述

  小明和小芳出去乡村玩,小明负责开车,小芳来导航。

  小芳将可能的道路分为大道和小道。大道比较好走,每走1公里小明会增加1的疲劳度。小道不好走,如果连续走小道,小明的疲劳值会快速增加,连续走s公里小明会增加s2的疲劳度。

  例如:有5个路口,1号路口到2号路口为小道,2号路口到3号路口为小道,3号路口到4号路口为大道,4号路口到5号路口为小道,相邻路口之间的距离都是2公里。如果小明从1号路口到5号路口,则总疲劳值为(2+2)2+2+22=16+2+4=22。

  现在小芳拿到了地图,请帮助她规划一个开车的路线,使得按这个路线开车小明的疲劳度最小。

输入格式

  输入的第一行包含两个整数n, m,分别表示路口的数量和道路的数量。路口由1至n编号,小明需要开车从1号路口到n号路口。

  接下来m行描述道路,每行包含四个整数t, a, b, c,表示一条类型为t,连接ab两个路口,长度为c公里的双向道路。其中t为0表示大道,t为1表示小道。保证1号路口和n号路口是连通的。

输出格式

  输出一个整数,表示最优路线下小明的疲劳度。

样例输入

6 7

1 1 2 3

1 2 3 2

0 1 3 30

0 3 4 20

0 4 5 30

1 3 5 6

1 5 6 1

样例输出

76

样例说明

  从1走小道到2,再走小道到3,疲劳度为52=25;然后从3走大道经过4到达5,疲劳度为20+30=50;最后从5走小道到6,疲劳度为1。总共为76。

数据规模和约定

  对于30%的评测用例,1 ≤ n ≤ 8,1 ≤ m ≤ 10;

  对于另外20%的评测用例,不存在小道;

  对于另外20%的评测用例,所有的小道不相交;

  对于所有评测用例,1 ≤ n ≤ 500,1 ≤ m ≤ 105,1 ≤ a, bnt是0或1,c ≤ 105。保证答案不超过106。

思路

       我的思路是这样的。

       1、大体上是利用广搜,一步一步的向外扩展(使用一个vector<Node>数组进行维护)。当找到目标时n时,记录下此时消耗的能量mixNum。注意,此时广搜并没有结束,mixNum不一定为最终的结果,如图1所示,路线二比路线一更加短。

       接下来仍然是一步一步的向外扩展,但此时我们拥有了一个限制条件mixNum 。在接下来的扩展时如果遇见的消耗能量大于mixNum  的节点就不需要加入到表中了;如果又再次找到了目标n,此时更新一遍mixNum 的值。

       通过一点一点的拓展,不断地逼近真值,直到数组为空时结束广搜。输出mixNum 即可。

201712-4 试题名称:	行车路线 80分_用例

      2、你以为结束了?想来并没有吧!!我做完上面几步提交之后只得了40分,显示运行出错。问题在与宽搜的时候没有判重,也没有对没必要的节点进行忽略处理。如图1中3节点走向4节点,又回到3节点,虽然最终都会被消除掉,但出现了不必要的处理,最终也就爆栈了。最终我给每一个节点添加了一个用来比较的vector<Info>bijiao[505]的集合。

比较的原则为:

                        /**

                        **  第一次经过点i时,耗能为a1,小道为b1

                        **  第二次经过点i时,耗能为a2,小道为b2

                        **  情况一:a2>=a1&&b2>=b1  //此时不需要将第二次进入的信息加入到表中了

                        **  情况二:a1>a2&&b1<b2 || a1<a2&&b1>b2  //需要加入表中 ,需要把比较信息加入比较表中

                        **  情况三:a2<=a1&&b2<=b1  //此时需要更新用来比较的信息

                        **/

     3、但最终我只得了80分,我觉得肯定还有问题没想到或者就是代码没写对!!!二者必有其一

201712-4 试题名称:	行车路线 80分_广搜_02


WA代码

#include<iostream>
#include<vector>
using namespace std;
class Node{
public:
int id=-1;
int xiaodao=0;
int haoneng=0;

};
class Edge{
public:
int otherEdge;
int flag=false;//默认非小道
int length=0;

};
class Info{
public:
int a,b;
};
vector<Edge>g[505];
vector<Info>bijiao[505];//用来比较的集合
vector<Node>vs;
int n,m;
int mixNum=2147483647;//最小值
int main(){
//没有针对等效路的解决:1-2 1-3 2-4 3-4

cin>>n>>m;
for(int i=0;i<m;i++){
int t, a, b, c;
cin>>t>>a>>b>>c;
Edge e;
e.flag=t;
e.length=c;
e.otherEdge=a;
g[b].push_back(e);
e.otherEdge=b;
g[a].push_back(e);
}
Node node;
node.id=1;
vs.push_back(node);
Info minfo;
minfo.a=0;
minfo.b=0;
bijiao[1].push_back(minfo);
while(!vs.empty()){
// for(int i=0;i<vs.size();i++){
// cout<<vs[i].id<<" "<<vs[i].haoneng<<" "<<vs[i].xiaodao<<"---------------------------"<<i<<endl;
// }cout<<"##################################################################"<<endl;
// system("pause");
vector<Node>vx;
for(int i=0;i<vs.size();i++){
Node n1=vs[i];
Node n2;
for(int j=0;j<g[n1.id].size();j++){
Edge e=g[n1.id][j];
n2.id=e.otherEdge;
if(e.flag){ //小道
n2.haoneng=e.length*e.length+2*e.length*n1.xiaodao+n1.haoneng;
n2.xiaodao=n1.xiaodao+e.length;
}else{ //不是小道
n2.haoneng=e.length+n1.haoneng;
n2.xiaodao=0;
}
if(n2.id==n){
mixNum=n2.haoneng<mixNum?n2.haoneng:mixNum;
}else{
if(n2.haoneng<mixNum){//判断一下是否可以加入表中

/**
** 第一次经过点i时,耗能为a1,小道为b1
** 第二次经过点i时,耗能为a2,小道为b2
** 情况一:a2>=a1&&b2>=b1 //此时不需要将第二次进入的信息加入到表中了
** 情况二:a1>a2&&b1<b2 || a1<a2&&b1>b2 //需要加入表中 ,需要把比较信息加入比较表中
** 情况三:a2<=a1&&b2<=b1 //此时需要更新用来比较的信息
**/

if(bijiao[n2.id].size()==0){//初次比较,直接添加
Info info;
info.a=n2.haoneng;
info.b=n2.xiaodao;
bijiao[n2.id].push_back(info);
vx.push_back(n2);
}else{

int quanxian=0;
Info info2;
for(int k=0;k<bijiao[n2.id].size();k++){
Info info=bijiao[n2.id][k];
int a1,a2,b1,b2;
a1=info.a;
b1=info.b;
a2=n2.haoneng;
b2=n2.xiaodao;
if(a2>=a1&&b2>=b1){
//无需操作
quanxian=3;
break;
}else if((a1>a2&&b1<b2 )||( a1<a2&&b1>b2)){
info2.a=a2;
info2.b=b2;
quanxian=quanxian>1?quanxian:1;
} else if(a2<=a1&&b2<=b1){
bijiao[n2.id][k].a=a2;
bijiao[n2.id][k].b=b2;
quanxian=quanxian>2?quanxian:2;
}
}
if(quanxian==1){
vx.push_back(n2);
bijiao[n2.id].push_back(info2);
}else if(quanxian==2){
vx.push_back(n2);
}else if(quanxian==3){
//无需操作
}
}
}
}
}
}
vs.clear();
vs=vx;
}
cout<<mixNum;
return 0;
}