http://poj.org/problem?id=2965
方法一:
我是照着1753改的 直接从0到16枚举 有些多余的不影响运行的 代码就没删
不理解的话可以直接看一下1753的题解: https://www.cnblogs.com/dyhaohaoxuexi/p/10920790.html
#include <stdio.h> #include <stdlib.h> #include <iostream> #include <string.h> using namespace std; int flag=0,ms[4][4]; void change(int newm[][4],int *b,int m) { int i; for(i=0;i<m;i++) { int t=b[i]; int tx=b[i]/4; int ty=b[i]%4; int j=0; for(j=0;j<4;j++) newm[tx][j]=!newm[tx][j]; for(j=0;j<4;j++) newm[j][ty]=!newm[j][ty]; newm[tx][ty]=!newm[tx][ty]; //本身这个点翻转了两次 一定要记得再翻转过来 } } int panduan(int newm[][4],int *b,int m) { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) if(newm[i][j]!=1) { return 0; } cout<<m<<endl; for(i=0;i<m;i++) { cout<<b[i]/4+1<<' '<<b[i]%4+1<<endl; } exit(0); //直接退出 不然可能会有多余的方案输出 } void digui(int *a,int *b,int t,int now,int n,int m) { int i,j; if(t==m) { int newm[4][4]; for(i=0;i<4;i++) for(j=0;j<4;j++) newm[i][j]=ms[i][j]; change(newm,b,m); if(panduan(newm,b,m)) flag=1; return; } else { for(i=now;i<=n-(m-t);i++) { b[t]=a[i]; digui(a,b,t+1,i+1,n,m); } } } int main() { int i,j; char m[4][4]; int a[16]={0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15}; int b[16]; for(i=0;i<4;i++) { cin>>m[i]; for(j=0;j<4;j++) { if(m[i][j]=='-') ms[i][j]=1; else ms[i][j]=0; } } for(i=0;i<=16;i++) { memset(b,0,sizeof(b)); digui(a,b,0,0,16,i); if(flag==1) { break; } } }
方法二(相当精妙):
我是在这里看到的:
https://blog.csdn.net/qq_41552508/article/details/79837582
根据分析可以得出结论,把开关本身以及其同一行同一列的开关都进行一次操作,最终结果是只有开关本身状态发生变化,其他所有开关状态都不变。
策略找到之后,那我们就想,如果对于所有关闭着的开关都进行一次上述策略,那么肯定是能把冰箱打开的,下面我们要做的就是把一些无用的,重复的操作去掉即可。
#include <cstdio> #include <cstring> #include <string> #include <iostream> using namespace std; int a[4][4]; int main() { /* 当我想把模块中某一个格子改变时,就需要把这个格子的行、列上每一个格子都改变一次 所以没遇到一次‘+’就把这个格子行列上所有格子改变一次 最后对于那些改变次数是奇数次的格子输出即可 */ for(int i = 0;i < 4;i++) { string c; cin>>c; for(int j = 0;j < 4;j++) { if(c[j] == '+') { for(int k = 0;k < 4;k++) { a[i][k]++; if(k!=i) a[k][j]++; } } } } int sum = 0; //记录奇数点个数 for(int i = 0;i < 4;i++) { for(int j = 0;j < 4;j++) { if(a[i][j] % 2 != 0) { sum++; } } } printf("%d\n",sum); for(int i = 0;i < 4;i++) { for(int j = 0;j < 4;j++) { if(a[i][j] % 2 != 0) { printf("%d %d\n",i+1,j+1); } } } return 0; }