USACO Section 2.2 Party Lamps - 看清本质就简单!

29 篇文章 0 订阅

    这题乍一看吓一跳...范围挺大的...想了也有一个小时才想通...看清本质!!

    总共就4个按钮...如果我1,2,3,4都按过一次了..再按一下1 or 2 or 3 or 4灯的情况不和只按了2,3,4 or 1,3,4 or 1,2,4 or  1,2,3一样吗?因为一个按钮按两次就相当于没按..那么实际上能出现的最多情况也就是C(1,4)+C(2,4)+C(3,4)+C(4,4)=17种~~枚举出这些情况..当且仅当当前所案件的次数与所需要的按键次数之差为偶数(不断地来回按)并且得到的情况是满足输入的要求的就找到了一个~~

    输出的话再排个序行了~~

Program:

/*  
ID: zzyzzy12  
LANG: C++  
TASK: lamps
*/    
#include<iostream>    
#include<stdio.h>    
#include<string.h>    
#include<math.h>    
#include<algorithm>    
#include<queue>
using namespace std;  
struct node
{
     int s[102];  
}ans[1001],h;
int N,C,x,s[102],num;
bool f;
bool cmp(node a,node b)
{
     int i;
     for (i=1;i<=N;i++)
     if (a.s[i]!=b.s[i]) return a.s[i]<b.s[i];    
}
void search(node h,int step,int key)
{
     int i,j;
     node k;
     if (step<=C && (C-step)%2==0)
     {
           for (i=1;i<=N;i++)
              if (s[i]!=-1 && s[i]!=h.s[i]) goto A;
           ans[++num]=h;    
           if (num!=1)
           {        
                 for (i=1;i<num;i++)
                 {
                       f=true;
                       for (j=1;j<=N;j++)
                          if (ans[num].s[j]!=ans[i].s[j]) f=false;
                       if (f) break;
                 }
                 if (f) num--;
           }
     }   
     A: ;
     for (i=key;i<=4;i++)
     {
           if (i==1) 
           {
                 k=h;     
                 for (j=1;j<=N;j++) k.s[j]=1-k.s[j];
           }
           else
           if (i==2)
           {
                 k=h;     
                 for (j=1;j<=N;j++) if (j%2) k.s[j]=1-k.s[j];
           }
           else
           if (i==3)
           {
                 k=h;     
                 for (j=1;j<=N;j++) if (j%2==0) k.s[j]=1-k.s[j];
           }           
           else
           if (i==4)
           {
                 k=h;     
                 for (j=1;j<=N;j++) if (j%3==1) k.s[j]=1-k.s[j];
           }           
           search(k,step+1,key+1);
     }
}
int main()
{
     freopen("lamps.in","r",stdin);
     freopen("lamps.out","w",stdout);     
     scanf("%d%d",&N,&C);  
     memset(s,-1,sizeof(s));
     while (scanf("%d",&x) && x!=-1) s[x]=1;
     while (scanf("%d",&x) && x!=-1) s[x]=0;
     num=0;
     for (int i=1;i<=N;i++) h.s[i]=1;
     search(h,0,1);        
     if (num)
     {  
           sort(ans+1,ans+1+num,cmp);  
           int j,i;  
           for (i=1;i<=num;i++)
           {
                 for (j=1;j<N;j++) printf("%d",ans[i].s[j]);
                 printf("%d\n",ans[i].s[N]); 
           }
     }else printf("IMPOSSIBLE\n");
     return 0;   
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值