poj 1222 EXTENDED LIGHTS OUT

xiaoxiao2021-02-28  105

题目链接:没错,就是这里 【题意】 给你五行六列的一个图,图中只有1或者0。每一个点都表示这里有一个灯,0表示灯熄灭,1表示灯开启。现在每个灯那里都有一个开关,但是这个开关不仅控制当前位置的灯,还控制了和它相邻的灯的状态,每次拨动一个开关都可以使它和它相邻的灯(如果有的话)的状态改变(开变为关,关变为开)。然后问你怎么操作可以让当前状态的所有灯全变为熄灭。

【分析】

稍微分析一下,显然有: 1,操作对应着位操作中的异或。 2,一个开关最多只拨动一次。 3,控制一个灯的多个开关如果拨动了两次,那么当前灯的状态不改变。

下面证明一下2。

如果存在一个开关拨动了多次,那么显然有((n>>1)<<1)次操作时无效的,所以一定有每个灯只能波动一次。

然后显然会有一个方程就是

F(i,j)=x(i,j)^b(i,j)^b(i-1,j)^b(i+1,j)^b(i,j+1)^b(i,j-1);

其中,F表示操作后灯的状态,x表示之前的灯的状态,b表示灯的开关是否操作过。

然后我们接着分析可以得到:将初始状态调成全为关闭和将全为关闭调成初始状态是一个完全相同的过程。但是显然后者更容易实现,所以我们转换一下问题就行。

然后直接根据前面的推导列出方程。剩下的就交给高斯消元了啦啦啦。。。

【代码】

#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> #include<stack> #include<set> #include<map> #include<queue> #include<sstream> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) #define MSi(a) memset(a,0x3f,sizeof(a)) #define sin(a) scanf("%d",&(a)) #define sin2(a,b) scanf("%d%d",&(a),&(b)) #define sll(a) scanf("%lld",&(a)) #define sll2(a,b) scanf("%lld%lld",&(a),&(b)) #define sdo(a) scanf("%lf",&(a)) #define sdo2(a,b) scanf("%lf%lf",&(a),&(b)) #define inf 0x3f3f3f3f #define lson l, m, rt << 1 #define rson m+1, r, rt << 1|1 typedef pair<int,int> PII; #define A first #define B second #define pb push_back #define MK make_pair #define ll long long template<typename T> void read1(T &m) { T x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } m = x*f; } template<typename T> void read2(T &a,T &b) { read1(a); read1(b); } template<typename T> void read3(T &a,T &b,T &c) { read1(a); read1(b); read1(c); } template<typename T> void out(T a) { if(a>9) out(a/10); putchar(a%10+'0'); } template<typename T> void outn(T a) { if(a>9) out(a/10); putchar(a%10+'0'); puts(""); } using namespace std; const int Maxm=8; int a[Maxm*Maxm][Maxm*Maxm]; int x[Maxm*Maxm]; void init(void) { memset(a,0,sizeof(a)); for(int i=0; i<5; i++) for(int j=0; j<6; j++) { int t=i*6+j; a[t][t]=1;//自己会影响自己 if(i > 0) a[t][(i-1)*6+j] = 1; if(i < 4) a[t][(i+1)*6+j] = 1; if(j > 0) a[t][i*6+j-1] = 1; if(j < 5) a[t][i*6+j+1] = 1; } } void Gauss(void) { memset(x,0,sizeof(x)); for(int row=0,columu=0; row<30&&columu<30; row++,columu++) { int max_row=row; for(int r=row+1; r<30; r++) if(abs(a[r][columu])>abs(a[max_row][columu])) max_row=r; if(a[max_row][columu]==0) { row--; continue; } if(max_row!=row) for(int c=columu; c<31; c++) swap(a[row][c],a[max_row][c]); for(int r=row+1; r<30; r++) { if(a[r][columu]!=0) for(int c=columu; c<31; c++) a[r][c]^=a[row][c]; } } for(int row=29; row>=0; row--) { x[row]=a[row][30]; for(int c=row+1; c<30; c++) x[row] ^= (a[row][c]&&x[c]); } } int main() { // freopen("in.txt","r",stdin); int T; read1(T); for(int t=1; t<=T; t++) { printf("PUZZLE #%d\n", t); init(); for(int i=0; i<5; i++) for(int j=0; j<6; j++) { read1(a[i*6+j][30]); } Gauss(); for(int i=0; i<5; i++) for(int j = 0; j<6; j++) { printf(j==5?"%d\n":"%d ",x[i*6+j]); } } return 0; }
转载请注明原文地址: https://www.6miu.com/read-48156.html

最新回复(0)