本地和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
一开始我的代码是这样的:
但是提交到oj上第一个数据就wa了。
还好codevs给了测试数据,出错的数据是这样的:
10
3
4
8
5
oj上测出来的结果是这样的:
我的devcpp测
adc9
出来的结果:
换了VS2017后测出来的结果和devcpp一样。
由于我是第一次遇到这种情况,感觉非常匪夷所思,甚至一度以为是自己的眼睛出了毛病。后来开始怀疑是oj的bug,于是乎疏忽了对自己代码的检查。
第一天没有找出来原因。但是我怎么能就这样放弃呢,于是不甘心的我在今天重写了一份代码,这次用的是递推的方法:
这份代码一次就AC了,这就彻底打消了我一开始觉得oj有bug的疑虑。那到底是哪里出错了呢?于是我开始细心检查自己的代码,终于发现
我居然少了一句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。
综上所述,如果你也遇到这样的情况,多半都是你的运行环境遮盖了你代码中的错误,第二种可能不是没有,但很少。还是好好琢磨一下代码哪里出错了吧。
题目描述 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。
综上所述,如果你也遇到这样的情况,多半都是你的运行环境遮盖了你代码中的错误,第二种可能不是没有,但很少。还是好好琢磨一下代码哪里出错了吧。
相关文章推荐
- Java同样的汉字在服务器和本地的电脑上URLencode 出来的结果不一致
- Java同样的汉字在服务器和本地的电脑上URLencode 出来的结果不一致
- 打印同样一个数据,竟然出现不同的结果,解决方法。
- 打印同样一个数据,竟然出现不同的结果,解决方法。
- Deep Learning 31: 不同版本的keras,对同样的代码,得到不同结果的原因总结
- 求助水晶报表动态饼图显示、求助进行数据查询和把查询结果用图表比较出来
- 数据的图形可视化[R语言结果GML引发出来的调查]
- 将两个表中的主键不同数据查找出来并添加到一张新表中的sql示例
- 易语言读不出来mysql的数据的原因
- oracle中将EXP出来的数据IMP进不同的表空间
- JPA 本地查询,结果数据获取错误
- Graph.DrawString在graph在不同scaletransform情况下出来结果不一样的问题
- 题目1两个有符号的-999~+999的数相加(字符串式,负数是四位,正数是三位,)结果在屏幕上打出来,数据存在栈中
- 大家看看这个php+mysql留言板哪里有错误?不同的地方下载几次同样的了,这么大留言板设计出来,还有小问题!败在细节。
- 将数据从一个数据库烤出来,想放到另一个数据库,由于某些原因不能直接执行sql文件,笨方法这是一个excel函数
- 同样的一辈子,不同的结果!
- 【加密】sha1:不同数据散列出来的指纹永远不同,而相同数据散列出来的指纹永远相同(理论上)。而且永远无法从散列后的数据恢复原始数据。
- Android手机6.0系统查询本地视频音频数据库查不出来数据的办法
- vue 使用过滤器数据值和显示值不同原因
- mysql数据库在不同的服务器,无法进行数据传输,或者导入导出数据错误,原因分析