zoukankan      html  css  js  c++  java
  • USACO Section2.2 Party Lamps 解题报告 【icedream61】

        lamps解题报告
    ------------------------------------------------------------------------------------------------------------------------------------------------
    【题目】
      N个灯,编号1~N。有4个开关,和C次改变某个开关状态的机会,试问最终所有灯的亮灭情况可能有哪些?
        一号开关:改变所有灯的状态。
        二号开关:改变所有奇数号灯的状态。
        三号开关:改变所有偶数号灯的状态。
        四号开关:改变所有3K+1号灯的状态(k=0,1,2,…)。
      初始时,所有灯都是亮的。
    【输入】
      第一行一个数,N。
      第二行一个数,C。
      后两行,每行有空格分割的一些数,以-1结尾,给出的是此题的“额外限制条件”:
        第三行所出现的数,表示编号为这些的灯最终应当处于“亮”的状态,即最后输出时这些位置的数字应当为1;
        第四行所出现的数,表示编号为这些的灯最终应当处于“灭”的状态,即最后输出时这些位置的数字应当为0。
    【输出】
      所有符合题目要求的状态,每行一种状态,用N位的二进制数来表示所有灯的亮灭状态,从最高位到最低位依次是1号到N号灯。
      注意,请按照字典序输出。
    【数据范围】
      N=10~100
      C=0~10000
    【输入样例】
      10
      1
      -1
      7 -1
    【输出样例】
      0000000000
      0101010101
      0110110110
    ------------------------------------------------------------------------------------------------------------------------------------------------
    【分析】
      如果直接记录所有灯的状态,那么状态数是2的100次方种,明显超空间。
      简单观察一下,这道题的灯可以分为6组,分别是除以6模0~5这六组。那么,一号开关就是6组全改变,二、三号开关则是分别改变奇数组和偶数组,四号开关则是仅仅改变3K+1对应的两组。这样一来,所有灯的状态总共只有64种。
      继续分析,四个开关,一个初始状态,那么显然我们可以拨动开关0~4次,分别是一个开关都不变直到四个开关都变,就只有这五种情况了。也就是说,C的值只有0~4是有意义的,而一旦比4大,就说明必然灯被拨动了两次,那么可以让C减去2,让这个灯不被这样毫无意义的“玩”,结果显然是一样的。
      至此,我们把N变成了6,C变成了0~4,这个模型显然就简单多了。那么,我们只要看看题目最后的限制条件啦~
      依旧是映射到1~6号灯所代表的这6组灯上即可,因此这里便可能直接导致题目无解喽~
      这就是本题的思路了,余下的就是编程实现细节,不予赘述。
    ------------------------------------------------------------------------------------------------------------------------------------------------
    【总结】
      第四次AC,回顾自己这不到一个小时,我还真是“常怀懒惰之心”啊!
      两天没做题了,脑子又开始懒了,静不下心来细想,做得很慢错误也多。很简单的题,做的过程中犯了几个细节错误:
        1.第一次提交,把代码中main函数里第三个IMPOSSIBLE那种情况给忘了
        2.第二次提交,ok函数中if语句&运算的括号没加,导致运算符优先级错误
        3.第三次提交,main函数中最后一个循环并未使用kk来保证字典序输出

    ------------------------------------------------------------------------------------------------------------------------------------------------

    【代码】

      1 /*
      2 ID: icedrea1
      3 PROB: lamps
      4 LANG: C++
      5 */
      6 
      7 #include <iostream>
      8 #include <fstream>
      9 using namespace std;
     10 
     11 // p[101100]: 1,2,5 closed, 3,4,6 openned
     12 bool p[64]; // p[k]: can walk to state k
     13 bool d[64]; // d[k]: state d is right
     14 int r[6],w[4];
     15 int mark[6];
     16 
     17 int N,C;
     18 
     19 void go(int k,int c) // walk c steps from state k
     20 {
     21     if(!c) // get a final state
     22     {
     23         p[k]=true;
     24         return;
     25     }
     26 
     27     int t;
     28     t=k^63; go(t,c-1);
     29     t=k^21; go(t,c-1);
     30     t=k^42; go(t,c-1);
     31     t=k^9; go(t,c-1);
     32 }
     33 
     34 bool ok(int k) // return if the state is right
     35 {
     36     for(int i=0;i!=6;++i) // the lamps in group i
     37         if(mark[i]!=-1 && (k&(1<<i))!=(mark[i]<<i)) // the state of lamps in group i is right to mark[i]
     38             return false;
     39     return true;
     40 }
     41 
     42 void print(ostream &out,int k)
     43 {
     44     bool t[6];
     45     for(int i=0;i!=6;++i) t[i]=k&(1<<i);
     46     for(int i=0;i!=N;++i) out<<t[i%6];
     47     out<<endl;
     48 }
     49 
     50 int main()
     51 {
     52     ifstream in("lamps.in");
     53     ofstream out("lamps.out");
     54 
     55     in>>N>>C;
     56 
     57     while(C>=5) C-=2;
     58 
     59     p[63]=true;
     60     go(63,C);
     61     int x,y;
     62     for(int i=0;i!=6;++i) mark[i]=-1;
     63     for(in>>x;x!=-1;in>>x)
     64     {
     65         y=(x-1)%6;
     66         if(mark[y]==-1) mark[y]=1;
     67         else if(mark[y]==0)
     68         {
     69             out<<"IMPOSSIBLE"<<endl;
     70             in.close(); out.close();
     71             return 0;
     72         }
     73     }
     74     for(in>>x;x!=-1;in>>x)
     75     {
     76         y=(x-1)%6;
     77         if(mark[y]==-1) mark[y]=0;
     78         else if(mark[y]==1)
     79         {
     80             out<<"IMPOSSIBLE"<<endl;
     81             in.close(); out.close();
     82             return 0;
     83         }
     84     }
     85     //for(int i=0;i!=6;++i) cout<<"mark["<<i<<"]="<<mark[i]<<endl;
     86 
     87     bool t=false;
     88     for(int kk=0,k=0;k!=64;++k,kk=0)
     89     {
     90         for(int i=0;i!=6;++i) kk+=((bool)(k&(1<<i)))*(1<<(6-i-1));
     91         //cout<<"k= "; print(cout,k);
     92         //cout<<"kk="; print(cout,kk);
     93         //cout<<endl;
     94         if(p[kk] && ok(kk)) { print(out,kk); t=true; }
     95     }
     96     if(!t) out<<"IMPOSSIBLE"<<endl;
     97 
     98     in.close(); out.close();
     99     return 0;
    100 }
  • 相关阅读:
    《Effective C#》读书笔记——了解.NET内存管理机制<.NET资源管理>
    《Effective C#》读书笔记——条目13:正确地初始化静态成员变量<.NET资源管理>
    用创新和务实的精神开创反洗钱检查工作的新局面
    《谈谈具有中国特色的“全能型”程序员》(2009/12/11)
    EOM与程序员话题的开场白(2009/12/07)
    从事反洗钱工作要有一定的高度
    程序员漫谈(2009/12/08)
    怎样快速确定程序员编程的水平(2009/12/10)
    重视或应付!当前金融机构反洗钱面临的一个问题
    反洗钱法律法规
  • 原文地址:https://www.cnblogs.com/icedream61/p/4470937.html
Copyright © 2011-2022 走看看