派对灯(poj1176 Party Lamps)

探讨了在IOI晚宴上,通过四个特定按钮控制N盏灯的开关状态,根据给定的按钮按压次数C和部分灯的最终状态,求解所有可能的灯的最终配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description英文版

To brighten up the gala dinner of the IOI 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

Sample Output

0000000000
0101010101
0110110110

描述 中文版

为了照亮 IOI 的盛大晚宴,我们有一套从
1 到 N 编号的 N 色灯。灯连接到四个按钮:
按钮 1 – 按下此按钮时,所有指示灯将更改其状态:打开的灯都处于关闭状态,关闭的指示灯将打开。
按钮 2 - 更改所有奇数灯的状态。
按钮 3 - 更改所有偶数灯的状态。
按钮 4 – 更改编号为 3K+1(K >= 0)的灯的状态,即 1,4,7,…
有一个计数器 C 记录按钮按下的总数。
当聚会开始时,所有灯都打开,计数器 C 设置为零。
您将获得计数器 C 的值以及某些灯的最终状态
信息。编写一个程序,以确定 N 灯的所有可能的最终配置,这些配置与给定的信息一致,无需重复。

输入

您的程序是从标准输入读取。输入包含四行,描述可用灯的数量 N、按下按钮的 C 数以及最终配置中某些灯的状态。
第一行包含数字 N,第二行包含计数器 C 的最终值。第三行列出了您被告知在最终配置中处于 ON 的灯号,由一个空格分隔,并由整数 -1 终止。第四行列出了您被告知在最终配置中处于 OFF 的灯号,由一个空格分隔,并由整数 -1 终止。

参数 N 和 C 受以下参数的约束:10 <= N <= 100 1 <= C <= 100000 在最终配置中,您被告知为 ON 的灯数小于或等于 2。

输出

您的程序是写入标准输出。输出必须包含所有灯的所有可能的最终配置(不重复)。至少有一个可能的最终配置。每个可能的配置都必须写在不同的行上。每行都有 N 个字符,其中第一个字符表示灯 1 的状态,最后一个字符表示灯 N 的状态。0(零)代表关灯,1(一)代表打开的灯。配置应按二进制升序列出。

样本输入

10
1
-1
7 -1

样品输出

0000000000
0101010101
0110110110

题解:优化的DFS

1、通过几次操作会发现,按两次相同的按钮会抵消效果比如
按 112 等于 按 2
按 121 等于 按 2
所以最多只有4个不重复的按键,所以说不管按几次都能转化成按4个键的情况,比如按五次那么肯定有某个键按了两次效果会抵消相当于只按了三次,所以说,每次都相当于按4-c%2次,比如6,其实最多按4个次就能达到想要的状态。

2、然后就是简单的DFS,这里需要注意int型和char型的转化,转换成char型是为了好排序输出。还有就是结果可能会有相同的,比如 c = 6 并且是按123412得到的(实际上相当于只按了34),那么我们会先让c变成4,那么能达到34的可能是2234 可能是1134 等等,所以dfs时候肯定会搜出重复的,要去重。

更多的解释直接在代码里面,,,poj不支持#include<bits/stdc++.h>所以还是老老实实头文件一个一个敲吧

#include <iostream>
#include <string>
#include <vector>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
vector <string> ans;//存每种有效状态
int a[110];//目标串
int b[110];//去模拟C次按开关灯的状态
char tem[110];//为了将数组b模拟好的状态转换成String类型好去重,但数组b是从b[1]开始为灯的有效表示的,所以不能将b直接赋给string,于是就有了tem数组作为中间数组
int num = 0;//符合目标的个数
int n, c;
void num1()
{
    for (int i = 1; i <= n; ++i)
    {
        b[i] = !b[i];
    }
}
void num2()
{
    for (int i = 1; i <= n; i += 2)
    {
        b[i] = !b[i];
    }
}
void num3()
{
    for (int i = 0; i <= n; i += 2)
    {
        b[i] = !b[i];
    }
}
void num4()
{
    for (int i = 1; i <= n; i += 3)
    {
        b[i] = !b[i];
    }
}
void dfs(int icount)
{
    if (icount == c)//模拟按了c次开关
    {
        int f = 1;
        for (int i = 1; i <= n; ++i)
        {
            if (a[i] == -1) continue;
            if (a[i] != b[i])//说明模拟失败
            {
                f = 0; 
                break;
            }
        }
        if (f)//模拟成功,b数组里面的值就是c次开关后,n个灯的正确状态之一
        {
            num++;//符合目标的个数+1
            for (int i = 0; i < n; ++i)//为了便于排序,将n个灯的状态放入vector中
                tem[i] = b[i + 1] + '0';
            tem[n] = '\0';
           ans.push_back(tem);
        }
        return;
    }
    num1();
    dfs(icount + 1);
    num1();//还原上一步状态
    num2();
    dfs(icount + 1);
    num2();//还原上一步状态
    num3();
    dfs(icount + 1);
    num3();//还原上一步状态
    num4();
    dfs(icount + 1);
    num4();//还原上一步状态
}
int main()
{
    ios::sync_with_stdio(false);
    int x;
    cin >> n >> c;
    if (c > 4) c = 4 - c % 2;
    //初始化
    memset(a, -1, sizeof(a));
    while (cin>>x && x != -1)//输入已知的ON的灯号
        a[x] = 1;
    while (cin>>x && x != -1)//输入已知的OFF的灯号
        a[x] = 0;
    memset(b, 1, sizeof(b));//初始时所有灯都开着,所以初始化为1
    dfs(0);
    sort(ans.begin(), ans.end());//排序
    cout<<ans[0].c_str()<<endl;
    for (int i = 1; i < num; ++i)
    {
        if (ans[i] != ans[i - 1]) //去重
            cout<<ans[i].c_str()<<endl;
    }
    return 0;
}

原文链接
这里还有另一种做法,个人觉得规律是真的,不,好,找!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值