您的位置:首页 > 其它

本地和oj同样数据测出来不同结果的原因

2018-01-15 16:59 405 查看
1.11在做codevs1014装箱问题的时候,由于我编程水平不够,发生了一件令当时的我匪夷所思的事。特此记录,防止今后在出现类似问题。

题目描述 Description:

有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

输入描述 Input Description:

一个整数v,表示箱子容量

一个整数n,表示有n个物品

接下来n个整数,分别表示这n 个物品的各自体积

输出描述 Output Description

一个整数,表示箱子剩余空间。

样例输入 Sample Input

24

6

8

3

12

7

9

7

样例输出 Sample Output

0

一开始我的代码是这样的:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;

int** arr;
int v=0, n=0;
int* w;

void initial(int v, int n)
{
arr = new int*[v + 1];
for (int i = 0; i <= v; i++)
{
arr[i] = new int[n + 1];
for (int j = 0; j <= n; j++)
arr[i][j] = -1;
}
}

int fun(int i, int j)
{
if (j == 0)
return 0;
if (arr[i][j] != -1)
return arr[i][j];

if (w[j]>i)
arr[i][j] = fun(i, j - 1);
else
arr[i][j] = max(fun(i, j - 1), fun(i - w[j], j - 1) + w[j]);

}

int main()
{
cin >> v >> n;
w = new int[n + 1];
for (int i = 1; i <= n; i++)
cin >> w[i];
initial(v, n);
cout << v - fun(v, n) << endl;
return 0;
}


但是提交到oj上第一个数据就wa了。

还好codevs给了测试数据,出错的数据是这样的:

10

3

4

8

5

oj上测出来的结果是这样的:


我的devcpp测
adc9
出来的结果:


换了VS2017后测出来的结果和devcpp一样。

由于我是第一次遇到这种情况,感觉非常匪夷所思,甚至一度以为是自己的眼睛出了毛病。后来开始怀疑是oj的bug,于是乎疏忽了对自己代码的检查。

第一天没有找出来原因。但是我怎么能就这样放弃呢,于是不甘心的我在今天重写了一份代码,这次用的是递推的方法:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;

#define maxv 20000+10
#define maxn 30+10
int dp[maxn][maxv];
int v=0, n=0;
int vv[maxn];

void fun()
{
for(int i=0;i<=n;i++)
memset(dp[i],0,sizeof(dp[i]));

for(int i=n;i>=1;i--)
{
for(int j=0;j<=v;j++)
{
dp[i][j]=(i==n?0:dp[i+1][j]);
if(vv[i]<=j)dp[i][j]=max(dp[i][j],dp[i+1][j-vv[i]]+vv[i]);
}
}
printf("%d\n",v-dp[1][v]);
}

int main()
{
cin >> v >> n;
for (int i = 1; i <= n; i++)
cin >> vv[i];
fun();

return 0;
}


这份代码一次就AC了,这就彻底打消了我一开始觉得oj有bug的疑虑。那到底是哪里出错了呢?于是我开始细心检查自己的代码,终于发现

int fun(int i, int j)           //代码一
{
if (j == 0)
return 0;

if (arr[i][j] != -1)
return arr[i][j];

if (w[j]>i)
arr[i][j] = fun(i, j - 1);
else
arr[i][j] = max(fun(i, j - 1), fun(i - w[j], j - 1) + w[j]);

}


我居然少了一句return arr[i][j]!!!

加上这句后,一开始的那份代码就终于AC了。

好了,错误找到了,那么疑问又来了,为什么我本地能测出来结果呢?

原因在于运行平台的差别遮盖了代码的逻辑错误。

我不知道codevs它用的什么判的题。但是devcpp或者vs里有返回值的函数缺少return可能不会影响程序结果。这个和运行的ide和主机有关了。但是稍微严格一点的数据可能就会把错误检查出来了。比如:

如果把代码一中两个return注释掉:

msvc环境下的vs会告诉我这样的代码有问题



但同样的代码在devcpp里还可以运行。

如果只留下一个return



vs又不报错了。由此可见ide的不同对程序的运行有很大影响。

事实上,有返回值的函数,每个条件下都应该对应一个return语句的,但是如果少了,编译器也不一定能检查出来这种错误。程序运行时,不确定在运行阶段会出现什么问题。

将数组arr输出:



注意arr[5][2]处,根据输出结果可知先计算的arr[5][2]后计算的arr[5][1] ,计算arr[5][2]是这样的:arr[5][2]=fun(5,1);由于这时候还没有计算过arr[5][1],fun函数必定不会返回arr[5][1],而是在下面的语句中对arr[5][1]进行计算,这时候问题来了。arr[5][1]计算之后并没有返回他的值,那我是怎么得到的arr[5][2]???

事实上,fun(5,1)的值实际上就是eax寄存器的值,如果函数确实return了某个值,则会将该值放入eax寄存器并返回,但是fun(5,1)函数并没有执行到return语句。所以eax寄存器的值在执行函数时保持不变,直接返回,所以调用fun(5,1)之前寄存器里是什么值,返回的就是什么值。是一个不确定的值。vs和devcpp上正确真的只是凑巧而已,再来一组数据估计就GG。但是oj不见得就有这样的作用。由于运行环境的不同,就出现了本地和oj同样数据测出不同结果的原因。

还有系统或主机配置也可能导致oj和本地测出结果不同,举个例子,sizeof(int*)在64位电脑测试的话是8,而在oj上就不一定了。因为我们不知道oj他用的什么服务器判题。如果是32位的那就是4。

综上所述,如果你也遇到这样的情况,多半都是你的运行环境遮盖了你代码中的错误,第二种可能不是没有,但很少。还是好好琢磨一下代码哪里出错了吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐