HackerEarth的错误答案

时间:2014-08-31 20:07:10

标签: c algorithm bit-manipulation

问题链接:: 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的数量,并在单独的数组b[30]中记录1的位置。然后我将所有n整数存储在数组a[1000]中并检查所有整数,如果它们中的任何一个在我0中存储的位置都有b[30],如果有的话然后我将b [30]位置标记为标记,这样我就不会在a [1000]中的前面数字中再次检查该位位置。如果我为b [30]中存储的所有位置找到零,那么我打印是,否则我打印否。

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

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

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

问题陈述::(与HackerEarth一样)

  

您将获得一个数字Z和一个具有N个元素的集合S.您的工作是找到S的子集,使得给定数字的AND和该子集为零。如果此子集可以打印“是”,否则打印“否”

     

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

     

输出对于每个测试用例,如果子集可能,则打印是   打印编号

     

约束:1 <= T <= 100 1 <= N <= 1000 0 <= Ai&lt; = Z <= 1000000

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

示例输出 是 是 否

我的代码为示例输入提供了正确的答案,但在HackerEarth Submission上失败了。 请帮帮我们.. 感谢提前帮助.. :)

1 个答案:

答案 0 :(得分:1)

你的想法也很好,但你过于复杂了一点。你能想到如何更多地简化它(做比你描述的更少的东西,但保持相同的总体思路)?请继续阅读。

  

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

你不需要存储它们:你只会使用它们一次,所以不要费心存储它们。只需依次阅读并处理每一个。

  

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

不需要标记或打扰不再检查。你怎么能更容易地做到这一点?对于您在位置b[i]的数字中找到的每个零,只需递减每个i。然后,如果yes仅包含数字&lt; = 0。

,则会打印b

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

我意识到这并没有回答你的代码有什么问题。我的观点是,通过更多地考虑你的想法,你可以编写更好的代码,最有可能工作。在这种情况下,你可以摆脱许多不必要的行李,减少犯错误的机会。

至于你的代码到底错在哪里,有很多东西,但最重要的部分是:

    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以及该网站上的其他人,以便在尝试解决竞赛问题之前开始使用。