1. 程式人生 > >51nod 二染色問題 (逆向考慮)

51nod 二染色問題 (逆向考慮)

oid div 是否 flag and col ret names sam

題目:

技術分享圖片

註意,這題不是把一塊區域的黑翻成白、白翻成黑。

是把一塊區域全部翻成白或者翻成黑。

初始為全白,看能否翻出題中的情況。

我們假設翻轉若幹次能得到圖中的形狀,那麽我們找出最後一次的翻轉,即全W或者全B,讓這一塊區域置為隨機。(隨機可以看做B或者W中的一個)

直到把所有的這樣的翻轉全部找出來,置為隨機。

看最後是否有一定是B的點,如果有就說明無法翻轉到圖中的形狀,否則可以翻轉。

代碼:

#include <iostream>
#include <algorithm>
#include <map>
#include 
<vector> #include <set> #include <math.h> #include <queue> #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string> using namespace std; typedef long long ll; #define INF 2147483647 int t,n,k; char a[25][25]; //判斷以(x,y)為左上角的區域是否為同色,且不全為隨機。
bool isSame(int x,int y){ bool flagB = false,flagW = false; for(int i = x;i <= x+k-1; i++){ for(int j = y;j <= y+k-1; j++){ if(a[i][j] == B){ flagB = true; }else if(a[i][j] == W){ flagW = true; }
if(flagB && flagW){ return false; } } } if(!flagB && !flagW) return false; return true; } //以(x,y)為左上角的區域置為隨機 void makeRandom(int x,int y){ for(int i = x;i <= x+k-1; i++){ for(int j = y;j <= y+k-1; j++){ a[i][j] = R; } } } int main(){ cin >> t; while(t--){ cin >> n >> k; for(int i = 1;i <= n; i++) for(int j = 1;j <= n; j++) cin >> a[i][j]; while(true){ bool update = false; for(int i = n-k+1;i >= 1; i--){ for(int j = n-k+1;j >= 1; j--){ // cout << i << " " << j <<endl; if(isSame(i,j)){ makeRandom(i,j); update = true; } } } if(!update) break; } bool flag = true; for(int i = 1;i <= n; i++){ for(int j = 1;j <= n; j++){ if(a[i][j] == B){ flag = false; } } } if(flag){ cout << "Possible" << endl; }else{ cout << "Impossible" << endl; } } return 0; }

51nod 二染色問題 (逆向考慮)