トピックリンクします。https://vjudge.net/problem/POJ-1222
問題の意味:01の5×6の行列が与えられると、それ自体の上下左右反転状態を含み、各ポイントかが反転する二回フリップフリップ同等存在しないため、ポイントのときの状態を変更し、または反転します一度、最終的にはすべてゼロの行列を作ることができるものを覆すしようとしています。
アイデア:
練習1(列挙)が小さいため、データのは、決定に応じて、すべての可能な最初の行、6種類<< 1、行後の各列の合計を列挙することができ、これは条件の最後の行かどうかを決定することによって決定されます提案は実現可能です。
2アプローチ(ガウスの消去法):はっきり言うことは、今のような2×3の行列、と仮定され、今は目標状態を達成することです。
今、請求項6にランプの状態、6つの変数の等価。さらに6式、それぞれ6点最終状態。
それは方程式であるので、例えば、第1のランプのための0は、第0,1,3ランプに影響を与えることができる:(1 * X0)^(1 * X1)^(0 *×2)^(1 * X3)^(0 *×4)^(0 *×5)= 0、(式の右辺の0状態は最初0ランプ)を表します。
(1 *のX0)^(1 *×1)^(1 *×2)^(0 *×3)^(1 *×4)^(0 *×5)= 1:同様に式1のランプです。
式6は、列挙され、その後ガウス消去、XORおよび線形方程式の一般的な式を用いて解くことができるが、同じです。
トピックのそれぞれ30は、ランプ30の状態変数を示し、5×6 = 30の式です。
ACコード:
#include <cstdioを> する#include <CStringの> する#include <アルゴリズム> の#include <cmath> の#include <cstdlib> 使用して 名前空間STD。 const int型 MAXN = 40 ; INT T、CAS、[MAXN] [MAXN]、[MAXN] ANS。 ボイドのinit(){ memsetの(0、はsizeof (a)参照)。 memset(ANS、0、はsizeof (ANS))。 以下のために(int型 = Iを0 ; iは< 5 ; ++ I){ ため(INT J =0 ; J < 6 ; ++ J){ int型、T = i *が6 + jは、 [T] [T] = 1 。 もし(I> 0)[T] [T- 6 ] = 1 。 もし(iは< 4)[T] [T + 6 ] = 1 。 もし(J> 0)[T] [T- 1 ] = 1 。 もし(J < 5)[T] [T + 1 ] = 1 。 } } } ボイドガウス(INT EQU、INT VAR ){ int型、R = 0、C = 0 。 用(; R <EQU && C < VAR ; ++ R、++ C){ int型 MAXR = R。 用(int型 I = R + 1 <;私はEQUを++ i)が あれば(ABS([I] [C])> ABS([MAXR] [C])) MAXR = iは、 もし([MAXR] [C] == 0 ){ - R。 続け; } 場合(MAXR =!R){ ため(int型私は、C =;私は= < VARを ; ++ I) スワップ([R] [I]、[MAXR] [I])。 } のための(int型 I = R + 1、iはEQUを<; ++ I){ 場合([I] [C] == 0)続けます。 用(INT ; J <= J = C VAR ++; J) [I] [J] ^ = [R] [J]。 } } のための(int型 I = VAR - 1 ; I> = 0; - I){ ANS [I] [I] [= VARを]; 用(int型 J = I + 1 ; J <EQU ++ j)は ANS [I] ^ =([I] [J]&ANS [J])。 } } int型のmain(){ scanf関数(" %のD "、&T)。 一方、(T-- ){ INIT()。 以下のために(int型 iは= 0 ; iは< 30 ; ++ I) のscanf(" %dの"、および[I] [ 30 ])。 ガウス(30、30 )。 printf(" PUZZLEの#%d個の\ nを"、++ CAS)。 以下のために(int型 i = 0 ; iは< 5 ; ++ I){ ための(int型 J = 0 ; J < 6 ; ++ J){ のprintf(" %dの"、ANS [i *が6 + J])。 もし(!J = 5)のprintf(" " ); } のprintf(" の\ n "); } } 戻り 0 。 }