给出一个4*4的字符,+代表close,-代表open,每次可以选择一个字符进行变化。选择坐标(x,y)的字符会导致x行y列都反转。问你最少几次操作能把所有字符变成-。
此题有两种方法:1.枚举+位运算 2.高斯消元
1.暴力枚举每一行,如果此行状态有1就反转这个位置,复杂度24*4=216。
代码如下:
#include <iostream> #include <stdio.h> #include <string.h> #include <vector> using namespace std; typedef long long ll; int a[5]; char ch; int flag=0,ans; vector<pair<int,int> > ma; void turn(int x,int y) { a[x]=~a[x]; for(int i=0;i<4;++i) if(i!=x) a[i]^=(1<<y); } void dfs(int x) { if(flag) return ; if(x==4){ for(int i=0;i<4;++i) if(a[i]&15) return ; cout<<ma.size()<<endl; for(int i=0;i<ma.size();++i) cout<<ma[i].first<<' '<<4-ma[i].second<<endl; flag=1; } dfs(x+1); for(int s=1;s<1<<4;++s){ int tmp=0; int b[4]; for(int i=0;i<4;++i)b[i]=a[i]; for(int i=3;~i;--i){ if(s>>i&1){ ++tmp; ma.push_back(make_pair(x+1,i)); turn(x,i); } } dfs(x+1); while(tmp--) ma.pop_back(); for(int i=0;i<4;++i)a[i]=b[i]; } } int main(int argc, char **argv) { for(int i=0;i<4;++i) for(int j=3;~j;--j){ cin>>ch; if(ch=='+') a[i]|=1<<j; } dfs(0); return 0; }
2.高斯消元
跟POJ1830的开关问题一样,只不过这里相联系的开关是一行一列。
给出的是初始状态,要求目标状态全是open。
浙公网安备 33010602011771号