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 }
复制代码

 

posted on   IceDream61  阅读(360)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示