(方程式の解+ XOR問題は、ガウスの消去を切り替え)poj1222

トピックリンクします。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 ])。
        ガウス(3030 )。
        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 
}

 

おすすめ

転載: www.cnblogs.com/FrankChen831X/p/11769946.html