• 【中等难度】词编码(word)


    这个其实我没过。。。QAQ,但是好久没做出来题目了,就放宽一点时限嘻嘻,求不喷。

     原题地址:http://cdqz.openjudge.cn/noip/1009/

    题目描述

    一个发送机可以通过一条隧道发送一些以二进制代码组成的单词。在其尽头的接收机可以使用特殊技术恢复到最初的单词。每个单词最初都由0和1组成。所有的单词最-初长度都为n(4≤N  ≤l000)。当穿过隧道之后单词可能发生以下几种情况之一:

        (1)任意(一个)0被1取代

        (2)任意(一个)符号被删除

        (3)一个符号(0或1)被插入到任何位置

        (4)不改变

        我们知道最初的单词都具有以下性质:有1的位置号的总和是N+1的倍数,或者是0.

        Input

        N和转换后的单词,每个单词占一行。单词数不大于2001,不会有其它任何东西,除了一些空格与空行。

        Output

        你的程序应该打印输出原始序列的词,注意换行:    。

        若有多解,操作4优先,不行则按操作1,2,3优先。同一操作,按操作位置最先的优先(从左到右数起l,2,3,…N),还有操作2时,被删数列,先在被删数列添0,不行再添1。如果没答案输出-1

        Sample Input

        4

        0000

        011

        1011

        11011

        Sample Output

        0000

        0110

        1001

        1111

         附注(嘻嘻----)

    思路

                 本来我一直在想各种BFS滴。后来才发现只做一步,是的,只做一步,成败只有一步,简单了一点儿,然后又发现了一个亮点:对于每个密文只需要输出一个明文即可,所以O(2000*1000^2*4)后来我才发现这里1000是有平方的(ORZ)............算了,过一些是一些吧。。。

    代码

    //后面pluscheck分成1,2是因为题目规定一定要先添加0后添加1,只好copy一遍了。。。。 
    
    //2014-7-8 08:32:35
    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int N,M;
    int y[1005];
    char str[1005];
    int HIGHEST_CALLS;
    
    void ccout()           //-----普通输出----- 
    {
        if ((HIGHEST_CALLS==1)) return;
        for (int i=1;i<=M;i++) cout<<y[i];cout<<endl;
        HIGHEST_CALLS=1;
    }
    
    void check()           //-----普通检查-----
    { 
       if (HIGHEST_CALLS==1) return;
       int i;
       int flag=0;
       for (i=1;i<=M;i++) {if (y[i]==1) flag+=i; }
       if ((flag%N)==0) {ccout(); HIGHEST_CALLS=1;exit;}
    }
    
    void pluscheck1(int x)   //-----有一个0被删除了-----
    {
       if (HIGHEST_CALLS==1) return;
       int i;
       int flag=0;
       for (i=1;i<=M;i++) 
        {
             if (y[i]==1)
               { 
                    flag+=i; 
                    if (i>=x) flag++;
               }
        }
       if ((flag%N)==0) 
        {
            for (int i=1;i<x;i++) cout<<y[i];
               cout<<'0';
            for (int i=x;i<=M;i++) cout<<y[i]; cout<<endl;
            HIGHEST_CALLS=1;
            exit;
        }
    }
    
    void pluscheck2(int x) //-----有一个1被删除了-----
    {
       if (HIGHEST_CALLS==1) return;
       int i;
       int flag=0;
       for (i=1;i<=M;i++) 
        {
             if (y[i]==1)
               { 
                    flag+=y[i]; 
                    if (i>=x) flag++;
               }
        }
       if (((flag+x)%N)==0) 
         {
            for (int i=1;i<x;i++) cout<<y[i];
            cout<<'1';
            for (int i=x;i<=M;i++) cout<<y[i]; cout<<endl;
            HIGHEST_CALLS=1;
            exit;
         }
    }
    
    void reductioncheck(int x)   //-----一个符号(0或1)被插入到任何位置-----
    {
       if (HIGHEST_CALLS==1) return;
       int i;
       int flag=0;
       for (i=1;i<x;i++) {if (y[i]==1) flag+=i;}
       for (i=x+1;i<=M;i++) {if (y[i]==1) flag+=i-1;}
       if ((flag%N)==0) 
        {
            for (i=1;i<x;i++)cout<<y[i];
            for (i=x+1;i<=M;i++) cout<<y[i];cout<<endl;
            HIGHEST_CALLS=1;exit;}
    }
    
    int main()
    {
       //freopen("word.in","r",stdin);
       //freopen("word.out","w",stdout);
       int i,j,k,a,b,c;
       cin>>N;
       N++;  //-----主要是懒得把所有N都-1了-----
       while (cin>>str)  
       {
                
       HIGHEST_CALLS=0;        //-----最高指令:判断是否已经输出过解了。----- 
       M=strlen(str); 
       for (i=1;i<=M;i++) {  y[i]=int(str[i-1])-int('0');  }
       
       if (((N-1)==M)&&(HIGHEST_CALLS==0))          //-----判定自己是不是问题-----
          {
                check();
          }
       if (((N-1)==M)&&(HIGHEST_CALLS==0))            //-----有个0变成了1问题-----
          {
                for (i=1;i<=M;i++)
                {
                    if (y[i]==1) {y[i]=0; check(); y[i]=1;}
                }
          }
        if (((N-2)==M)&&(HIGHEST_CALLS==0))         //-----删除了一个符号问题-----
          {
                for (i=1;i<=M+1;i++) pluscheck1(i);
                for (i=1;i<=M+1;i++) pluscheck2(i);
          }
        if ((N==M)&&(HIGHEST_CALLS==0))               //-----插入了一个符号问题-----
          {
                for (i=1;i<=M;i++) reductioncheck(i);
          }
       if (HIGHEST_CALLS==0) cout<<"-1"<<endl;
       
       }
       return 0;
    }
    //2014-7-8 13:45:14 

    评测结果

     
     
    时限被我放宽到每个点15s才过了,我想哭。。。。还需要进一步的优化哇。。。。
    noip忘记取模的痛
  • 相关阅读:
    模板
    kuangbin带你飞
    BZOJ开荒记
    模板
    洛谷
    模板
    [蓝桥杯][2013年第四届真题]危险系数
    数位DP入门题
    备战2019蓝桥杯
    常用的数学符号
  • 原文地址:https://www.cnblogs.com/seekdreamer/p/3831363.html
Copyright © 2020-2023  润新知