POJ 2965 The Pilots Brothers'refrigerator列挙
1997 ワード
タイトル:http://poj.org/problem?id=2965
1753と同様に4*4の碁盤でもあり、スイッチロックによって碁盤上のすべてのロックがOPENとなり、1つのロックを開くと行と列のロックの状態が同時に変更されます.分析:
(1)同様に,各格子の鍵は1回だけ開くだけで十分である.2回開くと開かないに等しいからである.
(2)碁盤の状態は開錠の順序とは関係なく,開錠の個数と位置のみに関係する.
1つの鍵が開かないことを0-1で表すと,碁盤格子を求める01シーケンスに相当し,合計2^16の可能性があるため,列挙法を用いることができる.方法は1753と似ています(前のブログを参照).しかし、スイッチロックの位置を記録するためにpathを追加しました.コードは次のとおりです.
2965
Accepted
160K
63MS
C++
1430B
2011-07-29 22:17:01
1753と同様に4*4の碁盤でもあり、スイッチロックによって碁盤上のすべてのロックがOPENとなり、1つのロックを開くと行と列のロックの状態が同時に変更されます.分析:
(1)同様に,各格子の鍵は1回だけ開くだけで十分である.2回開くと開かないに等しいからである.
(2)碁盤の状態は開錠の順序とは関係なく,開錠の個数と位置のみに関係する.
1つの鍵が開かないことを0-1で表すと,碁盤格子を求める01シーケンスに相当し,合計2^16の可能性があるため,列挙法を用いることができる.方法は1753と似ています(前のブログを参照).しかし、スイッチロックの位置を記録するためにpathを追加しました.コードは次のとおりです.
#include <stdio.h>
#define ONLINE
void online()
{
#ifdef ONLINE
#else
freopen("2965.in", "r", stdin);
freopen("2965.out", "w", stdout);
#endif
}
int map = 0;
const int END = 0X0000;
const int SIZE = 16;
const int state[SIZE] = {
0xF888, 0xF444, 0xF222, 0xF111,
0x8F88, 0x4F44, 0x2F22, 0x1F11,
0x88F8, 0x44F4, 0x22F2, 0x11F1,
0x888F, 0x444F, 0x222F, 0x111F
};
int result = 17;
int path=0;//
void read()
{
char c;
for (int i=0; i < SIZE; i++)
{
c = getchar();
if (c == '+')
{
map = map << 1;
map = map ^ 1;
}//end if
else if (c == '-')
{
map = map << 1;
}
else{
i --;
}//end else
}//end for
}
void search(int idx, int step, int p)
{
if (step >= result)
{
return;
}
if (idx >= SIZE)
{
if (map == END && step < result)
{
result = step;
path = p;
}//end if
return;
}
p = p << 1;
p = p^1;
map = map ^ state[idx];
search(idx+1, step +1, p);
map = map^state[idx];
p = p >> 1;
p = p << 1;
search(idx+1, step, p);
p = p >>1;
}
void print()
{
printf("%d
", result);
//
int bit = 15;
for (int i=1; i <=4; i ++)
{
for (int j=1; j <= 4; j ++)
{
if ((path >> bit)&1 == 1)
{
printf("%d %d
", i, j);
}// end if
bit --;
}//end for
}//end for
}
int main()
{
online();
read();
search(0, 0, 0);
print();
return 0;
}
実行結果は次のとおりです.2965
Accepted
160K
63MS
C++
1430B
2011-07-29 22:17:01