【问题标题】:Wrong answer on HackerEarthHackerEarth 上的错误答案
【发布时间】:2014-10-25 02:11:40
【问题描述】:

问题链接::http://www.hackerearth.com/the-big-bang-challenge/algorithm/subset-and-4/

问题是给你一个数字Z 和一些n 整数。您必须找出是否存在 n 个整数的子集 AND(按位运算符)Z 给出零,如果存在则打印“是”,否则打印“否”。

我知道一个简单的方法就是将所有输入的 n 个数字和 Z 相加,看看它是否为零。但是当我第一次看到这个问题时,我并没有意识到这一点。我实际上对此感到非常愚蠢。

这是我在阅读问题时首先编写的代码::

#include <stdio.h>

int main()
{
    int t;
    int n;
    long int z;
    int i,j,x;
    long int a[1000];
    int b[30];
    int count,count2;
    int flag;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%ld %d",&z,&n);
        count=0;
        for(i=0;i<n;i++)
            scanf("%ld",&a[i]);

        for(i=0;i<30;i++)
            b[i]=-1;
        j=0;
        for(i=0;i<25;i++)
        {
            if(z&1==1)
            {
                b[j++]=i;
                count++;
            }
            z=z>>1;
        }

        flag=0;
        count2=0;
        for(i=0;i<n;i++)
        {

            for(j=0;j<count;j++)
            {
                x=a[i];
                if(b[j]!=-1)
                {
                    x=x>>b[j];
                //    printf("New x=%d\nx&1=%d\n",x,x&1);
                    x==x&1;
                    if(x==0)
                    {
                        count2++;
                        b[j]=-1;
                    }
                  //  printf("Count2=%d and Count1=%d\n",count2,count);

                }

            }
            if(count2>=count)
                {
                    flag=1;
                    break;
                }

        }
        if(flag==0)
            printf("No\n");
        else
            printf("Yes\n");
    }
    return 0;
}

我的代码实际上打算做什么?

在我的代码中,我检查整数 Z 的二进制表示并计算数字中出现的 1 的数量,并将 1 的位置记录在单独的数组 b[30] 中。我将所有n 整数存储在数组a[1000] 中,并检查所有整数是否在我存储在b[30] 中的位置有0,如果其中任何一个有,那么我标记那个b [30] 位置标记,因此我不会在 a[1000] 前面的数字中再次检查该位位置。如果我发现存储在 b[30] 中的所有位置都为零,那么我打印是,否则我打印否。

与我应该做的相比,我知道这是一个非常令人困惑和糟糕的算法。 但是,请帮助大家。我的代码在提交时给出了错误的答案。

例如:: Z=5,则 Z 的二进制将是1001,即1 在第 0 位和第 3 位。因此,在数组 b[30] 中,我将位为 1 的位置存储在 Z 中。就像这里,我将 0 存储在 b[0](对于 Z 中的第一个有效位),然后将 3 存储在 b [1](对于下一个有效位),我对 20 位执行此操作(根据我的需要),如果任何位为 1,则我将其位置存储在 b[j++] 中。

然后,我开始将我存储在 a[1000] 中的所有元素一个接一个地存储在 x 中,然后从我之前处理过的 b[30] 数组中取出 1 个位置,将 x 右移那么多位置并检查最右边的位是否为1。例如,我的a[1000]数组有2个元素,3和1。3是0011,我将3存储在x中,取b[0]然后执行x>>b[ 0],在这种情况下与 0011 相同(因为 b[0] 为 0)。然后我通过执行x&amp;1 检查最右边的位,它返回 1,因此该位不为零,所以我前进到 b[1],它是 3,然后我执行 x>>b[1],它给出0000,然后我检查 x&1,它给了我零。所以,现在我知道我在数组中有一个第三位为零的数字,所以我将 b[1] 标记为 -1,这样我就不会再次检查它以获取 a[1000] 中的下一个整数。然后我取1,它是a[1000]的第二个元素,然后执行与上面相同的步骤,我发现a[1000]中没有第0位为零的元素。所以,我没有元素在 Z 为 1 的位置有零位。所以,AND 永远不会为零,所以我打印 No

问题陈述::(在 HackerEarth 上)

给你一个数字 Z 和一个包含 N 个元素的集合 S。你的工作是找到一个 S 的子集,使得给定数字和这个子集的 AND 为零。如果这个子集是可能的,打印“是”,否则打印“否”

输入第一行包含测试用例T的数量。每个测试用例 包含两行,第一行包含两个数字 Z 和 N ,其中 Z 给定数字,N 是集合 S 的大小。第二行包含 N 子集 S 的元素。

如果子集可能,则输出每个测试用例打印 Yes 打印号。

约束:1

示例输入 3 10 2 2 0 10 3 1 1 1 5 3 1 5 3

样本输出 是的 是的 没有

我的代码为示例输入提供了正确答案,但在 HackerEarth 提交时失败。 请大家帮忙。。 感谢您提前提供任何帮助.. :)

【问题讨论】:

    标签: c algorithm bit-manipulation


    【解决方案1】:

    你的想法也不错,但你有点过于复杂了。你能想出如何更简化它(做的事情比你描述的要少,但保持相同的总体思路)?继续阅读以了解如何操作。

    我将所有 n 个整数存储在数组 a[1000]

    您不需要存储它们:您只会使用它们中的每一个,因此不必费心存储它们。只需依次阅读和处理每一个。

    并检查所有整数,如果它们中的任何一个在我存储在 b[30] 中的位置为 0,如果其中任何一个有,那么我将 b[30] 位置标记为已标记,这样我就不会检查再次为那个位位置

    无需标记或担心不再检查。你怎么能更容易地做到这一点?只需为您在位置i 的数字中找到的每个零递减每个b[i]。然后,如果b 仅包含数字yes。

    现在,我们消除了您想做的两件事,同时保持您的想法不变。这很好,因为如果我们做的工作越少,我们做错事的机会就越少。

    我意识到这并不能回答您的代码有什么问题。我的观点是,通过更多地思考你的想法,你可以编写更好的代码,这最有可能奏效。在这种情况下,你会摆脱很多不必要的包袱,减少犯错的机会。

    至于你的代码到底哪里错了,有不少,但最重要的是:

        for(i=0;i<n;i++)
        {
    
            for(j=0;j<count;j++)
            {
                x=a[i]; <= you are setting x for each j. 
                           You probably want this a level up, in the other loop?
                if(b[j]!=-1) <= don't need this the way I described it.
                {
                    x=x>>b[j]; <= b[j] has no bearing on how much you shift x by. 
                                  You probably meant x = x>>j? 
                                  But wait, that's wrong too, because we're in a loop, 
                                  so we'll shift by too much! Maybe x = x>>1?
                //    printf("New x=%d\nx&1=%d\n",x,x&1);
                    x==x&1; <= this doesn't do anything. Why? 
                               What is the difference between == and =?
                               Do you want to use =, or move this in the if below?
                    if(x==0)
                    {
                        count2++;
                        b[j]=-1;
                    }
                  //  printf("Count2=%d and Count1=%d\n",count2,count);
    
                }
            }
            if(count2>=count)
            {
                flag=1;
                break;
            }
        }
    

    我推荐一个编程教程,例如:http://www.cprogramming.com/tutorial/c-tutorial.html 和该网站上的其他教程,以便在尝试解决竞赛问题之前帮助您入门。

    【讨论】:

    • 您好先生.. 非常感谢您的回复。 :) 但是你提到了一些事情。首先,在我的 b[30] 数组中,我存储了我遇到的第一个 1 的位置。例如:5 是 1010,所以我在 b[0] 中存储 1,在 b[1] 中存储 3,这是位在 5 中的位置,即 1。其次,如果我的第一个数字在 a[1000] 中是 3,则是0011,然后我设置x = 3并移位x>>b [0],它只有3,然后我检查最右边的位,它不是零。然后我再次设置 x=x>>b[1] 给出 0000,然后检查最右边的位,即 0。然后将 b[1] 设置为 -1 并执行 count++。
    • 在外部 for 循环中,我检查 a[1000] 中的每个变量,看看它们在我存储在 b[30] 中的任何位置是否为零。谈到if(x&amp;1==0) 块,先生,我试过这样做,但我的 if 块从未执行。可能是因为 x&1 大约有 8 个零,我将它们与 1 个零进行比较。我不知道这是否是正确的原因,但它似乎没有用,如果可以解决这个问题,我会使用 Code Blocks IDE。我不知道如何使这项工作。 :(
    猜你喜欢
    • 1970-01-01
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多