プログラミングとアルゴリズム(b)は、アルゴリズムの基礎「消灯問題POJ-1222」列挙の最初の週」

https://www.cnblogs.com/huashanqingzhu/p/7278930.html

http://bailian.openjudge.cn/practice/1222
1222:EXTENDED LIGHTS OUT

この質問私は、6つの要素の最初の行が010101であると仮定すると、最初の行の列挙に場所がより困難と考え、明確に考えるように多くの時間を費やしています

、1111 1111 - 2つだけの状態、2つだけの各ランプ動作のオンとオフランプは、切り替えスイッチを押すとしないことにより、私は以前に、0から63まで、すなわち、0000 0000を列挙考え

この考えは間違っています。初期のランプ状態が決定されるため、あなたはいずれかが、周囲の照明に影響を与える可能性が押すので、この状態は、必ずしも1111 1111ありません。

キーは、最終的に列挙の状態が何であるか、それを明確にしているのですか?列挙は、0は操作がないことを示し、スイッチが1を表し、各ランプ、プレスの動作であります

このスイッチ押圧操作の最初の行、6つの可能な2の合計^。限り、最初の行は、各ランプの動作を決定するように、最初の行の状態でランプが最初の行線2が点灯した後に、決定されるランプの位置、ランプのスイッチング動作

説明

各行が6個のボタン、5行の合計を有し、ボタンのマトリックスを有します。各ボタンの位置は、ランプを持っています。ボタンが押されると、ボタンの位置や周囲の(上部、下部、左、右)の光が再び変更されます。ランプが最初に点灯している場合には、消滅されますされ、ランプが消灯し、点灯される場合。ランプ4の状態を変化させるマトリックスの横ボタン;マトリックスの隅のボタンは、ランプ3の状態を変更するために他のボタンは、ランプの状態5に変更します。

同図において、X印でマトリックスの左側が押下されたボタンを示し、マトリックスは、ランプの状態を変更する権利を表します。各マトリックスランプは初期状態を設定します。あなたはボタンを押して、というようになるまでの各ランプが消灯します。隣接ボタン、複数のランプが押下されると、キャンセル動作が他の動作をもたらすであろう。次の図は、第2の列のボタンの第3及び第5行が押され、行2の状態では、ランプの列4は変化しません。

あなたは、すべてのライトがオフになっているだけのように、押したボタンを決定するプログラムを書くことです。上記の規則によると、私たちは、1)第2プレスで同じボタンが第一押しは、生成された結果を相殺することを知っています。したがって、唯一の各ボタンを1回押すの最大値; 2)各ボタンが押下された順序は、最終結果に影響を及ぼさない; 3)各ランプ点灯ランプの最初の行の2行目に対応するボタンを押してください、あなたは最初の行のすべての光を消すことができます。繰り返しが続く、ランプは全て1,2,3,4-行を消すことができます。同様に、ボタン1,2,3,4,5列を押すと、ランプ5の前にオフにすることができます。

エントリー

5行、6桁(0又は1)を含む各行。隣接する二つの数字の間に単一のスペースで区切られています。0ランプの初期状態が消滅する表し、1の初期状態は、ランプが点灯していることを示し

輸出

5行、6桁(0又は1)を含む各行。隣接する二つの数字の間に単一のスペースで区切られています。1は、対応するボタンを押す必要を表し、0は、対応するボタンを押す必要がないことを示します。

サンプル入力

0 1 1 0 1 0
1 0 0 1 1 1
0 0 1 0 0 1
1 0 0 1 0 1
0 1 1 1 0 0

サンプル出力

1 0 1 0 0 1
1 1 0 1 0 1
0 0 1 0 1 1
1 0 0 1 0 0
0 1 0 0 0 0

問題解決の分析 

出典:北郭威先生

•  第2回押して、単一のボタンを、それが第一のプレスが生成された結果を相殺するので、唯一までの各ボタンを一度押す必要
•  各ボタンが押されたため、最終的な結果には影響ありません
•  のを各ランプ点灯ランプの線1と、第2行に対応するボタンを押し、すべてのライトが最初の行をオフにする
•は  それを繰り返し、すべてのランプ1、2、3、4行を消すことができ 

最初の考え:

オフすべてのかどうかを確認するために、最後の光を計算し、各状態のために、全ての可能なボタン(スイッチ)の状態を列挙する。
各ボタンは、2つの状態(押され又は押されていない)を有し、30個のスイッチの合計は、状態の数は2 30 も、タイムアウトを。

状態の数を減らすためにどのようにそれを列挙?
基本的な考え方:  部分がある場合は、ローカルの状態が決定されると、その後、残りの状態の残りは一つだけ、あるいはnの数種を決定することができ、その後のみをローカル状態ができ列挙する必要があります。 

この質問には、「ローカル」の存在が意味するか?
観察を通して、ことがわかった最初の行が1ようになっている  「ローカル」 

最初の行で識別された各番組のスイッチング動作は、スイッチング動作の後、光の特定の行につながる場合がオンであるので、光の一部はオフです。
(i番目の列が配置されていると仮定して)ランプ番号へのライン1から外れ、その後、唯一の方法は、2行目のスイッチを押すことで、私は、列番目。(1行目のスイッチが使い果たされているため、スイッチ及び第三の行は最初の行に影響を与えないであろう)
全てのランプ1の最初の行にはオフになって、  第2の実施の形態の妥当ラインスイッチング動作のみです。

第二列のスイッチング動作後、三行目のみの操作と合理的プログラムを切り替え、2行目のランプを消灯します。だから、最後の行のスイッチング動作が唯一のプログラムです。
限り、Aで示される最初の行に敷設操作方式として、プログラムの動作は、残りの行に唯一を決定することです。

:すべてのライトの最後の行がオフであるかどうか、プログラムの最後の行のスイッチング動作を計算し、最後の行の後、スイッチング動作を見て
、そうであれば、状態Aは、溶液でない場合、状態は溶液Aではないが、第一再試行する別の状態からライン1。 

列挙動作プログラム、状態数が2 ^最初の行のみである= 64 

状態の練習のない、より少ない数はありませんか?
最初の行を列挙、状態の数は2 ^である= 32

コード出典:北郭威の先生は、わずか数追加や変更コメントを作ります。

/ * 
http://bailian.openjudge.cn/practice/1222
1222:EXTENDED LIGHTS OUT
ハードレベル
* /


書式#include <メモリ> 
書式#include <iostreamの> 
の#include < 文字列 > 
の#include <CStringの>

使用して 名前空間STD;
 int型 GETBIT(チャー C、INT I)   // ビットの値を取得
{
     // Cチャー間GETビット番号I 
    リターン(C >> I)とを1。;
}
ボイド SetBit(チャー&C、int型 Iは、int型の V)が// 特定の位置に置くか、または0.1 
{
     // V「ビットが私の中のSET Cチャー番号
    IF (V)
    {
        C | =(1 << I);
    }
    
    {
        C&=〜(1 << I);
    }

}
ボイドフリップ(チャー&C、int型 I)の// 1ビット反転
{
     // チャーC「ビットをランクIフリップ。 
    C ^ =(1 << I)を、
}

ボイド OutputResult(int型の T、チャー結果[])// 出力結果
{
    裁判所未満 << " PAZZLEの#" <<トン<< てendl;
    以下のためにint型 i = 0 ; iは< 5 ; iは++ 
    {
        INT J = 0 ; J < 6 ; J ++ 
        {
            COUT << GetBit(結果[I]、j)は、
            もし(J < 5 
                裁判所未満 << "  " ;
        }
        coutの << てendl;
    }
}

int型のmain()
{
    チャー oriLights [ 5 ]; // 元の入力
    チャーライト[ 5 ]; // 途中計算結果
    チャー結果[ 5 ]; //は、操作の出力端を切り替え、スイッチが表すプレス、0は動作を表していない
    チャー switchsと、// 行スイッチ情報
    INT T。
    CIN >> T;
    int型、T = 1 ; T <= T、T ++ 
    {
        memset(oriLights、0はsizeof(oriLights))。// 省略した場合ではありません?
        以下のためにint型 i = 0 ; iは< 5 ; iは++ 
        {
            INT J = 0 ; J < 6 ; J ++ 
            {
                int型秒;
                cinを >> 秒;
                SetBit(oriLights [i]は、J、S)。
            }
        }

        INT N- = 0 ; N- < 64   ; N - ++)// 操作スイッチの最初の行トラバース64種類
        {
            memcpyを(ライト、oriLights、はsizeof (oriLights));
            switchs = N-; //が前提とスイッチ操作方式は、最初の行0が必要

            int型 iは= 0 ; iが< 5 ; ++ i)は
            {
                結果[I] =のswitchs; // i行目のスイッチ操作スキーム保存
                INT J = 0 ; J < 6。、J ++)// i行目のランプに従って変形例を
                {
                     IF(GETBIT(switchs、J ))// 1に等しいj番目のビットがswitchsはi番目の行、j番目のボタンを押す必要を示し、0に等しい、ボタンを押す必要はありませ示し
                    {
                         IF(J> 0 
                            フリップ(点灯[I]、J - 1); // 左光変更 
                        フリップ(点灯[I]、J)を; // スイッチポジションランプを変更
                        IF(J < 5。 
                            フリップ(点灯[I]、J + 1); // 右のランプを変更します

                    }
                }
                もし(iは< 4 
                    ライト[I + 1 ] = ^ switchs; // ランプが次の行に変更 
                [I] = switchsライト; // I + 1行目のスイッチ操作方式は、i行目のランプの状態によって決定される
            }
             IF [(点灯4 ] = = 0 
            {
                OutputResult(T、結果)。
                破ります;
            }

        }
    }
    リターン 0 ;
}


 

おすすめ

転載: www.cnblogs.com/focus-z/p/11373319.html