2011.12.22 poj1029 暴力枚举【learn from others】

来源:互联网 发布:淘宝mac口红靠谱代购 编辑:程序博客网 时间:2024/05/03 16:28

从POJ-DP集合问题里按顺序做到这道题,结果发现这道题本质不是DP问题(当然,也有牛人能用DP解答,显然我不是牛人)。

自己上午做了一个上午,写了好多遍,WA了,然后自己自我思考找出了好几个极端例子,包括DISCUSS里面的两个极端例子,吃午饭前想出两个极端例子,以及午饭后回实验室的路上也在想,在进门前上楼梯的时候想到一个反例,都改正过来了,最后提交仍旧WA了,心灰意冷。这道题就WA6次,遇到过好多次这种WA很多次甚至十多次,二十次的题目了。感叹自己技不如人。


自己原来的思路如下:

先统计=的情况,所有在=两端的都是真币,标记好它们。

出现在<左边的标记light,右边的标记heavy。

出现在>左边的标记heavy,右边的标记light。

如果同时有标记light和heavy,那么说明这个货币同时在不等式的“小于方“和”大于方“出现过,而已知只有一个假币,那么说明,这种货币肯定是真币。

然后不断的淘汰。最后看能否确定。

但是实际上这样有很多漏洞,例如反例:

5枚货币,比较过程如下:

3 = 4

2 < 3

2 < 5

表面上最后状态为

1 unkown

2 light

3 normal

4 normal

5 heavy

表面上同时有light 和heavy,结果为不确定。 但是实际情况是:2号币为假币。

最后修改了类似的几处漏洞,不过仍旧WA。


后来看了别人的解题报告,发现人家聪明多了,想到:假币出现的次数与不等式出现的次数一样,并且同样通过=来确定真币。

写完后,我提交直接AC了。

今天的收获是:

1.我的智商确实不足,这个世界聪明的人太多了。有些事情的解法自己却想不到。

2.如果一道题目你WA达到3次(含)以上,那么往往说明思路出了错误,再修再补都无济于事。 因为这个时候往往是程序架构出了问题,无论你再怎么修补,再怎么改动,很大程度上都是无用功。 真正如果思路算法都对了,WA的次数应该很少,很多甚至能直接AC。

3.从代码量上也可以看出来,组后AC的代码只有87行,而之前自己修修补补的代码达到了300来行,代码越长,越可能错误。


附上代码:(learn from others but coding by myself)

//poj_1029_1
//learn from others
#include <iostream>
#include <cassert>
using namespace std;


int main()
{
//freopen("d.txt","r",stdin);
while( true ){
int N,K;
if( scanf("%d %d",&N,&K) == EOF )
break;
int total = 0;
bool unfake[1001] = { false };
int heavy_times[1001] = { 0 };
int light_times[1001] = { 0 };
int num[1001];
int nums;
for(int k=0; k<K; ++k)
{
scanf("%d",&nums);
for(int i=0; i<2*nums; ++i)
scanf("%d",&num[i]);
char tmp;
scanf(" %c",&tmp);
assert( tmp == '=' || tmp == '<' || tmp == '>' );
if( tmp == '=' )
{
for(int i=0; i<2*nums; ++i)
unfake[ num[i] ] = true;
}
else if( tmp == '<' )
{
++total;
for(int i=0; i<nums; ++i)
light_times[ num[i] ]++;
for(int i=nums; i<2*nums; ++i)
heavy_times[ num[i] ]++;
}
else if( tmp == '>' )
{
++total;
for(int i=0; i<nums; ++i)
heavy_times[ num[i] ]++;
for(int i=nums; i<2*nums; ++i)
light_times[ num[i] ]++;
}
}
int res_nums = 0;
int res_ind = -1;
for(int i=1; i<=N; ++i)
{
if( unfake[i] )
continue;
if( heavy_times[i] != 0 && light_times[i] != 0 )
continue;
else if( heavy_times[i] == 0 && light_times[i] == 0 )  //i既没有出现在等式中也没有出现在> 和<等式中
{
if( total == 0 )   //没有不等式
{
++res_nums;
res_ind = i;
}
}
else//heavy_times[i]和light_times[i]当中仅有一个为0另一个为非0
{
if( total == heavy_times[i] )
{
++res_nums;
res_ind = i;
}
//if( total == light_times[i] )
else if( total == light_times[i] )
{
++res_nums;
res_ind = i;
}
}
}
if( res_nums == 1 )
printf("%d\n",res_ind);
else
printf("0\n");
}
return 0;
}


原创粉丝点击