1. 程式人生 > >USACO 2.2 Party Lamps 【高能等效+規律枚舉】

USACO 2.2 Party Lamps 【高能等效+規律枚舉】

mes stream hid med space ace imp 基本操作 cnblogs

題在這:https://www.luogu.org/problem/show?pid=1468#sub

按鈕1:當按下此按鈕,將改變所有的燈:本來亮著的燈就熄滅,本來是關著的燈被點亮。

按鈕2:當按下此按鈕,將改變所有奇數號的燈。

按鈕3:當按下此按鈕,將改變所有偶數號的燈。

按鈕4:當按下此按鈕,將改變所有序號是3*K+1(K>=0)的燈。例如:1,4,7...

此題關鍵:找到4個按鈕之間的關系,可發現最終狀態只有少數(可枚舉的)幾種,又:四個操作的影響周期取最小公倍數後,發現 6個燈為一個變化周期,不管如何按按鈕,最終N個燈的狀態均是以6個燈為基本單位,N/6為循環次數的循環序列

一、首先,從基本操作入手,隨意搭配四個按鈕,且每種按鈕只能使用一次,可發現:(只考慮6個燈,0表示燈滅,1表示燈亮)

1 2 3 4

按1 ====》0 0 0 0 0 0

按2 ====》0 1 0 1 0 1

按3 ====》1 0 1 0 1 0

按4 ====》0 1 1 0 1 1

按1和2====》1 0 1 0 1 0 ====》相當於按3

按1和3 ====》0 1 0 1 0 1 ====》相當於按2

按1和4 ====》1 0 0 1 0 0

按2和3 ====》0 0 0 0 0 0 ====》相當於按1

按2和4 ====》1 1 0 0 0 1

按3和4 ====》0 0 1 1 1 0

按1、2、3====》相當於按2遍三 ====》不變

按1、2、4====》相當於按3和4

按1、3、4====》相當於按2和4 再加上不按 ====》1 1 1 1 1 1
共計8種最終狀態(紅色),故以後所有的狀態都是由這8個中的一個為基本循環得到的 完成它們的最少操作次數分別為:1,1,1,3,2,2,2就是按4這種情況,按4 可以一步,也可以三步或者三步以上(224)但是就是不能兩步達到,故設為3,把按一次的情況特判 二、又由: 按1和按2相當於按3; 按2和按3相當於按1; 按1和按3相當於按2; 按1按2和按3相當於不按; 由(一)和(二)得,c 等於任意操作次數時,我們均可以用(一)搭出規律骨架,用(二)擴充(一)中的操作使湊齊c個操作,以這8個結果為基礎,構造答案(只是為了證明正確性,不必輸出),最後,只輸出最終狀態,完畢。
下面為參考代碼(借鑒了“ly59782的博客”中的代碼): 技術分享
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int state[9][7]={
{0,0,0,0,0,0,0},
{0,0,0,0,0,0,0},//press 1
{0,0,0,1,1,1,0},//press 3 & 4
{0,0,1,0,1,0,1},//press 2
{0,0,1,1,0,1,1},//press 4
{0,1,0,0,1,0,0},//press 1 & 4
{0,1,0,1,0,1,0},//press 3
{0,1,1,0,0,0,1},//press 2 & 4
{0,1,1,1,1,1,1} //not pressing
};
int c,n,x,a[8];
int minn[9]={0,1,2,1,3,2,1,2};
bool flag=0;

int main()
{
    freopen("lamps.in","r",stdin);
    freopen("lamps.out","w",stdout);
    for(int i=1;i<=6;i++)
        a[i]=-1;
    cin>>n>>c;
    while(cin>>x,x!=-1)
    {
        int v=x%6;
        if(v==0) v=6;
        a[v]=1;        
    }
    while(cin>>x,x!=-1)
    {
        int v=x%6;
        if(v==0) v=6;
        a[v]=0;        
    }
    for(int i=1;i<=8;i++)
    {
        int f=1;
        for(int j=1;j<=6;j++)    
        {
            if(a[j]==-1)
                continue;
            if(a[j]!=state[i][j])
            {
                f=0;
                break;
            }
        }
        if(f==1&&(c>=minn[i]||(c==1&&i==4)))
        {
            for(int p=1;p<=n;p++)
            {
                int v=p%6;
                if(v==0) v=6;
                cout<<state[i][v];
                flag=1;
            }
            cout<<endl;
        }
    }
    if(!flag)
        cout<<"IMPOSSIBLE"<<endl;
    return 0;
}
View Code

USACO 2.2 Party Lamps 【高能等效+規律枚舉】