题意简述
4*4矩阵,填充+或-,改变某格符号将同时改变当前行和列所有的格的符号。
求最少经过多少次转换能使所有符号变为-,并输出任一种可行方案。
算法分析
本题与POJ-1753基本没有区别。仅仅换了壳,增加了输出一种可行方案。
在POJ-1753的基础上,DFS同时用一个16个一维01数组记录当前的转换方案。与当前最优解比较时,如果更优则替换已记录的最优方案。
Problem Status: AC。时间875ms,内存388k
——————————————————————分割线——————————————————————
优化:
1、与POJ-1753一样可以使用一个int型代替一维01数组,用位运算实现转换。(还没试,改天再说…)
2、在评测记录里看到一个内存16K,时间0ms的记录…估计和POJ-1753一样用了某种神奇的枚举…如果找到了代码或者算法会更新上来~
程序样例
#include<stdio.h> int finish(int s[]) { int i; for (i = 0; i < 16; i++) if (s[i] == 0) return 0; return 1; } void change(int s[], int pos) { int i; if (s[pos] == 1) s[pos] = 0; else s[pos] = 1; for (i = 0; i < 16; i++) if (i != pos) { if (i % 4 == pos % 4) if (s[i] == 1) s[i] = 0; else s[i] = 1; if (i / 4 == pos / 4) if (s[i] == 1) s[i] = 0; else s[i] = 1; } } void try (int s[], int at[], int a[], int pos, int step, int * ans) { int i; if (finish(s)) { if (step < * ans) { * ans = step; for (i = 0; i < 16; i++) a[i] = at[i]; } return; } if (pos > 15) return; change(s, pos); at[pos] = 1; try (s, at, a, pos + 1, step + 1, ans); change(s, pos); at[pos] = 0; try (s, at, a, pos + 1, step, ans); } int main() { int s[16]; int i, j, ans = 17, a[16] = { 0 }, at[16] = { 0 }; char t[5]; for (i = 0; i < 4; i++) { scanf("%s", t); for (j = 0; j < 4; j++) if (t[j] == '-') s[i * 4 + j] = 1; else s[i * 4 + j] = 0; } try (s, at, a, 0, 0, & ans); printf("%d\n", ans); for (i = 0; i < 16; i++) if (a[i] == 1) printf("%d %d\n", i / 4 + 1, i % 4 + 1); return 0; }
test~