ちょっと変わった問題設定。
https://yukicoder.me/problems/no/2824
問題
N*Nのグリッドがあり、各セルは0/1の値が設定されている。
- セル(r,c)に対し行動をすると、(r,0),(r,c),(0,c)に対し以下の処理が行われる。
- セル(r,c)に対し処理をすると、(r,c),((r-1)%N,c),(r,(c-1)%N),((r-1)%N,(c-1)%N)の4セルの01が反転する。
行動を繰り返し、全セルの値を0にできるか。できるなら行動の一例を示せ。
解法
1回の行動で0/1が変化するセルは、各列・各行偶数個なので、初期状態で1の個数は各列・各行で偶数でなければならない。
次に、セルの値の累積和を取ると、この行動は(r-1)行目と(c-1)列目を反転するのに相当する。
この処理を繰り返し、累積和も全部0になるように行動先のセルを選択しよう。
int N; int A[1010][1010]; int R[1010],C[1010]; vector<pair<int,int>> V; void solve() { int i,j,k,l,r,x,y; string s; cin>>N; FOR(y,N) { cin>>s; FOR(x,N) if(s[x]=='#') { A[y][x]=1; R[y]^=1; C[x]^=1; } } FOR(i,N) { if(R[i]||C[i]) { cout<<-1<<endl; return; } R[i]=C[i]=0; } if(N==1) { cout<<0<<endl; return; } N--; FOR(y,N) FOR(x,N) { if(y) A[y][x]^=A[y-1][x]; if(x) A[y][x]^=A[y][x-1]; if(y&&x) A[y][x]^=A[y-1][x-1]; if(A[y][x]) R[y]^=1,C[x]^=1; } if(N%2) { FOR(i,N) if(R[0]!=R[i]||R[0]!=C[i]) break; if(i<N) { cout<<-1<<endl; return; } } FOR(y,N) FOR(x,N) if(A[y][x]^R[y]^C[x]) V.push_back({y,x}); cout<<V.size()<<endl; FORR2(y,x,V) cout<<y+1<<" "<<x+1<<endl; }
まとめ
これ難易度設定難しそう。★3.5でも良い気もするし…。