Party Lamps【DFS】

Party Lamps

describe

To brighten up the gala dinner of the IOI’98 we have a set of N coloured lamps numbered from
1 to N. The lamps are connected to four buttons:
button 1 – when this button is pressed, all the lamps change their state: those that are ON are turned OFF and those that are OFF are turned ON.
button 2 – changes the state of all the odd numbered lamps.
button 3 – changes the state of all the even numbered lamps.
button 4 – changes the state of the lamps whose number is of the form 3K+1 (with K >= 0), i.e., 1,4,7,…
There is a counter C which records the total number of button presses.
When the party starts, all the lamps are ON and the counter C is set to zero.
You are given the value of counter C and information on the final state of some of the lamps. Write a program to determine all the possible final configurations of the N lamps that are consistent with the given information, without repetitions.

Input

Your program is to read from standard input. The input contains four lines, describing the number N of lamps available, the number C of button presses, and the state of some of the lamps in the final configuration.
The first line contains the number N and the second line the final value of counter C. The third line lists the lamp numbers you are informed to be ON in the final configuration, separated by one space and terminated by the integer -1. The fourth line lists the lamp numbers you are informed to be OFF in the final configuration, separated by one space and terminated by the integer -1.
The parameters N and C are constrained by:
10 <= N <= 100
1 <= C <= 10000
The number of lamps you are informed to be ON, in the final configuration, is less than or equal to 2.The number of lamps you are informed to be OFF, in the final configuration, is less than or equal to 2.

Output

Your program is to write to standard output. The output must contain all the possible final configurations (without repetitions) of all the lamps. There is at least one possible final configuration. Each possible configuration must be written on a different line. Each line has N characters, where the first character represents the state of lamp 1 and the last character represents the state of lamp N. A 0 (zero) stands for a lamp that is OFF, and a 1 (one) stands for a lamp that is ON. Configurations should be listed in binary ascending order.

Sample Input

10
1
-1
7 -1
第一行: N.
第二行: C 最后显示的数值.
第三行: 最后亮着的灯,用一个空格分开,以-1 为结束.
第四行: 最后关着的灯,用一个空格分开,以-1 为结束.

Sample Output

0000000000
0101010101
0110110110

题意

按钮1:当按下此按钮,将改变所有的灯:本来亮着的灯就熄灭,本来是关着的灯被点亮.
按钮2:当按下此按钮,将改变所有奇数号的灯.
按钮3:当按下此按钮,将改变所有偶数号的灯.
按钮4:当按下此按钮,将改变所有序号是3*K+1(K>=0)的灯.
一个计数器C 记录按钮被按下的次数.
当宴会开始,所有的灯都亮着,此时计数器C为0.

思路

模拟一下可以看出来灯泡状态说六个一循环的,在后续比大小和输出中都可以利用这一特性,不然可能会超时。
然后深搜每个按键不同状态下的2^4个状态,依次去看是否match题目中的要求就行了。

AC代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;

int n,m,c;
bool last[2][101]; //最后亮/暗的两个灯泡 
int pres[5];  //记录按键情况 
int key[101];   //记录亮灯情况
int cot[17][101]; //排序 

struct node{
    int i;
    int num;
}hod[17];

bool cmp(node a,node b){
    return a.num<b.num;
}

bool match(){  //是否满足条件 
    bool a,b,d;
    a=b=true;
    for(int i=1;i<=n;i++){ 
        if(last[0][i]==true)
            a=a&&(key[i]==1);
        if(last[1][i]==true) 
            b=b&&(key[i]==0);
    }
    int cnt=0;  //cnt 最少按次数
    for(int i=1;i<=4;i++)
           cnt+=pres[i];  
    if(cnt>c) d=false;
    else{
        if(cnt%2==c%2) d=true; //按奇数次偶数次相同效果(模拟) 
        else d=false;
    }
    return a && b && d;
}

void sim(){   //模拟按键效果 
    for(int i=1;i<=n;i++) 
        key[i]=1;
    if(pres[1]){
        for(int i=1;i<=n;i++)
            key[i]=1-key[i];
    }
       if(pres[2]){
        for(int i=1;i<=n;i+=2)
            key[i]=1-key[i];
    }
    if(pres[3]){
        for(int i=2;i<=n;i+=2)
            key[i]=1-key[i];
    }
    if(pres[4]){
        for(int i=1,k=0;i<=n;i=3*k+1){
            key[i]=1-key[i];
            k++;
        }
    }
}

void dfs(int t){ //t  当前按键序号 
    if(t==5){
        sim();
        if(match()){
            for(int i=1;i<=n;i++) 
                cot[m][i]=key[i];
            m++;
        }
        return;
    }
    for(int i=1;i>=0;i--){
        pres[t]=i;
        dfs(t+1);
    }
}

int main(){
    int num;
    m=0; //符合条件的总个数 
     cin>>n>>c;
    while(cin>>num){
        if(num==-1)  break;
        last[0][num]=true;
    }   
    while(cin>>num){
        if(num==-1)  break;
        last[1][num]=true;
    }   
    dfs(1);
    int k;
    for(int i=0;i<m;i++){
        hod[i].i=i;
        num=0;
        k=1;
        for(int j=6;j>-1;j--){    //前6位转化为十进制 
                num+=k*cot[i][j];
                k*=2;
        }
        hod[i].num=num;
         }
    sort(hod,hod+m,cmp);
    for(int i=0;i<m;i++){
        for(int j=1;j<=n;j++)
            cout<<cot[hod[i].i][j];
        cout<<endl;
    }
    if(m==0) cout<<"IMPOSSIBLE"<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值