题目:http://poj.org/problem?id=2965
和1753很类似,也是一个4*4的棋盘,通过开关锁,来使得棋盘上所有的锁都是OPEN,当打开一个锁的时候,会同时修改行和列锁的状态。分析:
(1)同样的,每个格子的锁只要开一次就够了,因为如果打开两次,等于没有打开。
(2)棋盘的状态跟开锁的顺序没有关系,只跟开锁的个数和位置有关系。
如果用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\n", 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\n", 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 |