题目链接: http://poj.org/problem?id=1681

题意: 有一个包含 n * n 个方格的正方形, w 表示其所在位置为白色, y 表示其所在位置为黄色. 对 (i, j) 位置进行一次操作则 (i, j), (i + 1, j), (i - 1, j), (i, j - 1),  (i, j + 1) 位置的颜色变为原来的相反状态, 输出让所有方格都变成白色所需的最少操作步数, 若不能使所有方格都变成白色,则输出 inf .

思路: 这题和 poj 1222 (题解: http://www.cnblogs.com/geloutingyu/p/7565405.html) 类似, 同样也可以枚举第一行的所有操作, 或者解 mod2 方程组.

解法1:

注意要求出所有解法然后取操作数最小值.

 #include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std; const int inf = 1e9;
const int MAXN = 1e2;
int mp[MAXN][MAXN], sol[MAXN][MAXN];
int n, ans = inf; int check(void){
int gel[MAXN][MAXN], cnt = ;
memcpy(gel, mp, sizeof(mp));
for(int i = ; i <= n; i++){
if(sol[][i]){
cnt++;
gel[][i] ^= ;
gel[][i - ] ^= ;
gel[][i + ] ^= ;
gel[][i] ^= ;
gel[][i] ^= ;
}
}
for(int i = ; i <= n; i++){
for(int j = ; j <= n; j++){
if(gel[i - ][j]){
cnt++;
sol[i][j] = ;
gel[i][j] ^= ;
gel[i][j - ] ^= ;
gel[i][j + ] ^= ;
gel[i - ][j] ^= ;
gel[i + ][j] ^= ;
}else sol[i][j] = ;
}
}
for(int i = ; i <= n; i++){
if(gel[n][i]) return inf;
}
return cnt;
} void dfs(int m){
if(m > n){
ans = min(ans, check());
return;
}
sol[][m] = ;
dfs(m + );
sol[][m] = ;
dfs(m + );
} int main(void){
int t;
string s;
cin >> t;
while(t--){
cin >> n;
for(int i = ; i <= n; i++){
cin >> s;
for(int j = ; j < s.size(); j++){
if(s[j] == 'w') mp[i][j + ] = ;
else mp[i][j + ] = ;
}
}
ans = inf;
dfs();
if(ans == inf) cout << "inf" << endl;
else cout << ans << endl;
}
return ;
}

解法2:

注意对于存在变元的情况需要枚举变元的所有组合情况取操作数最小值.

 #include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std; const int inf = 1e9;
const int MAXN = 3e2;
int equ, var;//有equ个方程,var个变元,增广矩正行数为equ,列数为var+1,从0开始计数
int a[MAXN][MAXN];//增广矩正
int free_x[MAXN];//用来存储自由变元(多解枚举自由变元可以使用)
int free_num;//自由变元个数
int x[MAXN];//解集 int Gauss(void){//返回-1表示无解,0表示有唯一解,否则返回自由变元个数
int max_r, col, k;
free_num = ;
for(k = , col = ; k < equ && col < var; k++, col++){
max_r = k;
for(int i = k + ; i < equ; i++){
if(abs(a[i][col] > abs(a[max_r][col]))) max_r = i;
}
if(a[max_r][col] == ){
k--;
free_x[free_num++] = col;//这个是变元
continue;
}
if(max_r != k){
for(int j = col; j < var + ; j++){
swap(a[k][j], a[max_r][j]);
}
}
for(int i = k + ; i < equ; i++){
if(a[i][col] != ){
for(int j = col; j < var + ; j++){
a[i][j] ^= a[k][j];
}
}
}
}
for(int i = k; i < equ; i++){
if(a[i][col] != ) return -;//无解
}
if(k < var) return var - k;//返回自由变元个数
for(int i = var - ; i >= ; i--){
x[i] = a[i][var];
for(int j = i + ; j < var; j++){
x[i] ^= (a[i][j] && x[j]);
}
}
return ;
} void solve(void){
int op = Gauss();
if(op == -) cout << "inf" << endl;//无解
else if(op == ){//存在唯一解
int sol = ;
for(int i = ; i < var; i++){
sol += x[i];
}
cout << sol << endl;
}else{//存在多解,需要枚举自由变元找到最小需要的操作数
int sol = inf;
int tot = << op;//有op个变元,每个变元可取0或1,共有1<<op总情况
for(int i = ; i < tot; i++){//二进制枚举,i二进制位上为1的取1,为0的取0
int cnt = ;
for(int j = ; j < op; j++){
if(i & ( << j)){//当前第j位变元取1
x[free_x[j]] = ;
cnt++;
}else x[free_x[j]] = ;
}
for(int j = var - op - ; j >= ; j--){
int idx;
for(idx = j; idx < var; idx++){
if(a[j][idx]) break;
}
x[idx] = a[j][var];
for(int l = idx + ; l < var; l++){
if(a[j][l]) x[idx] ^= x[l];
}
cnt += x[idx];
}
sol = min(sol, cnt);
}
cout << sol << endl;
}
} int main(void){
int t, n;
string s;
cin >> t;
while(t--){
cin >> n;
equ = var = n * n;
for(int i = ; i < n; i++){
cin >> s;
for(int j = ; j < n; j++){
int cnt = i * n + j;
if(s[j] == 'w') a[cnt][var] = ;
else a[cnt][var] = ;
x[cnt] = ;
}
}
for(int i = ; i < equ; i++){//构造增广矩阵
int x1 = i / n;
int y1 = i % n;
for(int j = ; j < var; j++){
int x2 = j / n;
int y2 = j % n;
if(abs(x1 - x2) + abs(y1 - y2) < ) a[j][i] = ;
else a[j][i] = ;
}
}
solve();
}
return ;
}

最新文章

  1. 1.1ASP.NET Web API 2入门
  2. 线性时间的排序算法--桶排序(以leetcode164. Maximum Gap为例讲解)
  3. Ubuntu安装SSH服务
  4. poj 2185(二维kmp)
  5. Nagios 安装及微信短信提醒
  6. 调用webservice,解析返回数据为xml格式的字符串,进行数据绑定
  7. 【案例】舒邑:一个女装品牌的奇葩打法-@i黑马
  8. LAMP配置参考地址
  9. javascript语句语义大全(6)
  10. oracle:批量插入不同方案对比
  11. python排序 sorted()与list.sort() (转)
  12. PHP关联查询
  13. UE4入门(二)建立和打开项目
  14. Sql_server基本操作
  15. 【iCore4 双核心板】DEMO V1.0 测试程序发布
  16. Laravel中APP_KEY起什么作用
  17. [PureScript] Break up Expressions into Cases in PureScript using Simple Pattern Matching
  18. 【大数据系列】安装Ambari
  19. CentOS定位、查找文件的命令
  20. Timer控件

热门文章

  1. 我的MyGeneration
  2. 机器学习:PCA(降噪)
  3. AngularJS:包含
  4. 第十章 深入理解Session与Cookie
  5. DAY11-MYSQL数据操作
  6. Hadoop集群 能打开50070端口不能打开8088端口 web浏览器界面
  7. maven手动安装oracle驱动到仓库
  8. [codeforces126B]Password
  9. 框架之 hibernate之各种查询
  10. MSScriptControl详解(可实现在C#等语言中调用JAVASCRIPT代码)