C++的一个小问题,大家帮忙看看

时间:2022-02-23 21:59:23
在做一道算法题时遇到了这个问题,不知道是什么原理,希望大家帮忙看看


#include<bits/stdc++.h>
using namespace std;
#define LL long long  
const int maxn=1e3+5;
const int inf=1e9+7;
int n,head[maxn],vis[maxn],tot;
LL d[maxn],
qx[maxn];//在某点时、最优情况下连续走了 多远小道 

struct edge{
int v,next,val,type;//     权值  小/大道 
}e[maxn*100*4];

struct node{
int v;
LL dis,pre;
node(){}
node(int v,LL dis,LL pre){
this->v=v;
this->dis=dis;
this->pre=pre;
}
friend bool operator<(node n1,node n2)  
    {  
        if(n1.dis==n2.dis)
return n1.pre>n2.pre;
return n1.dis>n2.dis; 
    }  
};

LL dj(int s,int t)
{
priority_queue<node>q;
d[s]=qx[s]=0;
q.push(node(s,d[s],qx[s]));
d[s+n]=qx[s+n]=0;
q.push(node(s+n,d[s+n],qx[s+n]));
while(!q.empty())
{
node te=q.top();
q.pop();
int u=te.v;
if(vis[u])
continue;
vis[u]=1;
for(int i=head[u];i+1;i=e[i].next)
{
int v=e[i].v;
if(vis[v])
continue;
if(e[i].type)
{//小道 
LL a=qx[u];
LL b=e[i].val;
LL  len=d[u]+b*b+2*a*b;
//LL len=d[u]+ e[i].val*e[i].val + 2*qx[u]*e[i].val;
if(d[v]>len||(d[v]==len&&qx[v]>qx[u]+e[i].val))
{//更新 u v 边 
d[v]=len;
qx[v]=qx[u]+e[i].val;
q.push(node(v,d[v],qx[v]));
}
}
else
{//大道 
if(d[v]>d[u]+e[i].val)
{
d[v]=d[u]+e[i].val;
q.push(node(v,d[v],qx[v]));
}
}
}
}
return min(d[t],d[n+t]);
}

void init()
{
tot=0;
for(int i=0;i<2*n;i++)
{
head[i]=-1;
d[i]=inf;
if(i<n)
qx[i]=0;
else
qx[i]=inf;
vis[i]=0;
}
}
void add(int u,int v,int type,int val)
{
e[tot].type=type;
e[tot].v=v;
e[tot].val=val;
e[tot].next=head[u];
head[u]=tot++;
}
int main()
{
int m;
//freopen("D:\\1.txt","r",stdin);
scanf("%d%d",&n,&m);
init();
while(m--)
{
int t,a,b,c;
scanf("%d%d%d%d",&t,&a,&b,&c);
a--;
b--;    //t==0    t==1
add(a,b+n*t,t,c); //a,b,0,c a,b+n,1,c
add(a+n,b+n*t,t,c);//a+n,b,0,c  a+n,b+n,1,c 
add(b,a+n*t,t,c);//b,a,0,c b,a+n,1,c
add(b+n,a+n*t,t,c);//b+n,a,0,c b+n,a+n,1,c
}
printf("%lld\n",dj(0,n-1));

}

如果把dj函数的for循环中

LL a=qx[u];
LL b=e[i].val;
LL  len=d[u]+b*b+2*a*b;


换成下面注释的那行,也就是

 LL len=d[u]+ e[i].val*e[i].val + 2*qx[u]*e[i].val;

其他都不换!这样里两份代码应该是等价的吧。但是传到oj,上面的代码可以满分,
,下面的代码总有两组数据过不了。希望大佬指点一下,感激不尽!




6 个解决方案

#1


[可能数据类型有问题,e[i].val为int,第2个式子加上强制类型转换试试看。, 请把题目贴出来?,
引用 2 楼 hdt 的回复:
请把题目贴出来?

问题描述
  小明和小芳出去乡村玩,小明负责开车,小芳来导航。
  小芳将可能的道路分为大道和小道。大道比较好走,每走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,连接a与b两个路口,长度为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,
引用 2 楼 hdt 的回复:
请把题目贴出来?

 对于30%的评测用例,1 ≤ n ≤ 8,1 ≤ m ≤ 10;
  对于另外20%的评测用例,不存在小道;
  对于另外20%的评测用例,所有的小道不相交;
  对于所有评测用例,1 ≤ n ≤ 500,1 ≤ m ≤ 105,1 ≤ a, b ≤ n,t是0或1,c ≤ 105。保证答案不超过106。, 代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。
提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
, 百度动态规划寻路 C++的一个小问题,大家帮忙看看]

#1


[可能数据类型有问题,e[i].val为int,第2个式子加上强制类型转换试试看。, 请把题目贴出来?,
引用 2 楼 hdt 的回复:
请把题目贴出来?

问题描述
  小明和小芳出去乡村玩,小明负责开车,小芳来导航。
  小芳将可能的道路分为大道和小道。大道比较好走,每走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,连接a与b两个路口,长度为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,
引用 2 楼 hdt 的回复:
请把题目贴出来?

 对于30%的评测用例,1 ≤ n ≤ 8,1 ≤ m ≤ 10;
  对于另外20%的评测用例,不存在小道;
  对于另外20%的评测用例,所有的小道不相交;
  对于所有评测用例,1 ≤ n ≤ 500,1 ≤ m ≤ 105,1 ≤ a, b ≤ n,t是0或1,c ≤ 105。保证答案不超过106。, 代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。
提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
, 百度动态规划寻路 C++的一个小问题,大家帮忙看看]