HDU 4272LianLianKan 2012长春网络赛F题(思维) 暴力,dfs可以水过,正解是状态压缩dp

  

LianLianKan

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1848    Accepted Submission(s): 584


Problem Description
I like playing game with my friend, although sometimes looks pretty naive. Today I invent a new game called LianLianKan. The game is about playing on a number stack.
Now we have a number stack, and we should link and pop the same element pairs from top to bottom. Each time, you can just link the top element with one same-value element. After pop them from stack, all left elements will fall down. Although the game seems to be interesting, it's really naive indeed. 
HDU 4272LianLianKan 2012长春网络赛F题(思维) 暴力,dfs可以水过,正解是状态压缩dp_第1张图片
To prove I am a wisdom among my friend, I add an additional rule to the game: for each top element, it can just link with the same-value element whose distance is less than 6 with it. 
Before the game, I want to check whether I have a solution to pop all elements in the stack.
 

Input
There are multiple test cases.
The first line is an integer N indicating the number of elements in the stack initially. (1 <= N <= 1000)
The next line contains N integer ai indicating the elements from bottom to top. (0 <= ai <= 2,000,000,000)
 

Output
For each test case, output “1” if I can pop all elements; otherwise output “0”.
 

Sample Input
   
   
   
   
2 1 1 3 1 1 1 2 1000000 1
 

Sample Output
   
   
   
   
1 0 0
 


        感想:暑期积分赛又跪了一场,一题都木有A啊,但是看了题解之后,竟然好多都是水过的,当时是自己先看了F,觉得很有把握,然后就开始写,大概二十分钟,WA了一发,仔细研究程序觉得木有问题,还是没有水过去。。。最后吉吉给了几个测试数据,我看了看,不能总是选5步里面第一个跟它一样的,比赛完后,听说可以找5步最后一个和他相同的,不过自己改成这样也没A掉衰死了TAT。。。当时想到了DFS,但是吉吉说深度太深,不好下手。让博博看一下是不是dp,然后分析了下状态可以保存,只是找不到转移方程还是什么。。吉吉的搜索K题WA掉了,博博的线段树A题也TLE,整个情绪也不是很好,只能自己继续磨那个题,到最后真的跪了。

         题目大意:给你一个栈,每次只能出栈顶和离栈顶五步以内(含五步)的元素,要求这个元素必须和栈顶相同。

                           可以把栈出空,输出1,否则输出0.

         解题思路:自己写了两种,一种是暴力找,详见AC代码1;

                           还有一种是DFS,这个相对严密一点,详见AC代码2.

                           不过正解却是   HDU 4272 LianLianKan 状态压缩DP

                                            只能说是水过,这个题的数据。。不想多说什么了。。。

         题目地址:LianLianKan


AC代码1:暴力求解

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int visi[1002],a[1002];

int main()
{
     int n,i,j,flag;
     while(~scanf("%d",&n))
     {
          for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
          if(n&1)
          {
               puts("0");
               continue;
          }
          flag=0;
          int t=0;
          memset(visi,0,sizeof(visi));
          while(t<n)   //到最后没消完的话可以继续消,此种有漏洞。就是可以先出去中间的
          {
            int flag1=0;
            for(i=n;i>1;i--)   
            {
               if(visi[i]) continue;
               int step=1;       //此处判断步数的去掉也可以AC。。。
               for(j=i-1;j>=0;j--)
               {
                    if(visi[j]) continue;
                    if(step>5) break;  //此处判断步数的去掉也可以AC。。。
                    step++;            //
                    if(a[i]==a[j])
                    {
                         visi[i]=visi[j]=1;
                         //cout<<i<<" "<<j<<endl;
                         flag1=1;
                         t+=2;
                         break;
                    }
               }
            }
            if(flag1==0)
            {
                flag=1;
                break;
            }
          }
          if(flag) puts("0");
          else puts("1");
     }
     return 0;
}

        不过 对于

       12
       5 2 4 3 1 5 2 1 3 4 1 1
       12
       1 3 3 5 5 4 4 1 2 3 3 2

       第一组应该输出1,第二组应该输出0.我说下我大概的思路。水过的原因就在这里,因为第二组数据输出也是1.因为我判断的如果栈非空的话就继续进行。例如第一组数据消去的位置是 12与11 9与4 8与5 7与2 6与1 10与3.

       而到了第二组数据,这样判断就过不了了。

            说测试数据很坑是因为上面如果去掉step判断五步神马的也可以过,这。。情何以堪啊。。。我竟然没水过去


然后参见AC代码2:DFS

#include<cstdio>
#include<string>
#include<iostream>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
int a[1005],visi[1005];
map<int,int> map1;

int dfs(int n)
{
    while(n>0&&visi[n])
        n--;
    if(n==0)return 1;
    int step=0,j=n-1;
    while(step<5)
    {
        if(j<=0)
           return 0;   //没有找到5步以内可以到达的点
        if(visi[j])
        {
            j--;
            continue;
        }

        if(a[n]==a[j])
        {
            visi[j]=1; visi[n]=1;
            if(dfs(n-1)) return 1;
            visi[j]=0; visi[n]=0;  //回溯的过程
        }
        j--; step++; //找不到的话,step+1,j-1.
    }
    return 0;
}


int main()
{
    int n,flag;
    while(~scanf("%d",&n))
    {
        map1.clear();
        flag=0;
        memset(visi,0,sizeof(visi));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            map1[a[i]]++;
            //统计个数,如果某个数出现奇数次的话,直接输出1,否则会TLE
        }
        if(n&1)
        {
            printf("0\n");
            continue;
        }

        map<int,int>::iterator x;
        //第二维存放数量
        for(x=map1.begin();x!=map1.end();x++)
        {
            if((x->second)&1)
            {
                flag=1;
                break;
            }
        }
        if(flag==1)
        {
            printf("0\n");
            continue;
        }
        printf("%d\n",dfs(n));
        //cout<<"1"<<endl;   //此处直接输出1也可以AC。。。。
    }
    return 0;
}
          

          代码相对来说还是比较严谨的,但是当我听说不需要dfs,先判断&1,再判断个数&1.不符合就直接输出1即可。。然后当时瞬间就石化了。。。。如上面直接输出1.

你可能感兴趣的:(HDU,思维,网络赛,积分赛)