poj-3279 Fliptile

呂振麒 bio photo By 呂振麒 Comment

傳送門:

Fliptile

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
int T,M,N,K,I,a,b,c,cnt;
int di[] = {0,-1, 0, 1, 0}; // to move
int dj[] = {0, 0, 1, 0,-1};
bool arr[20][20], flip[20][20], tmp_flip;
pii ans;    // {times, flip of first row}

void init(){
  N = getint(), M = getint();
  for(int i=0;i<N;i++)for(int j=0;j<M;j++)
    arr[i][j] = getint();   // need to be reversed
}
inline bool ok(int &i, int &j){
  return not(i<0 or j<0 or i>=N or j>=M);
}
inline bool need(int i, int j){
  int ii,jj;
  tmp_flip = 0;
  for(int k=0;k<5;k++)
    if(ok(ii=i+di[k], jj=j+dj[k]))
      tmp_flip ^= flip[ii][jj];
  return tmp_flip^arr[i][j];
}
int cal(){
  int times = 0;    // 注意,此時第0列已經flip,未記錄
  for(int i=0;i+1<N;i++)
    for(int j=0;j<M;j++)
      if(need(i,j)) flip[i+1][j]=1, ++times;

  for(int i=0;i<M;i++){
    times += flip[0][i];  // 補紀錄第0列
    if(need(N-1, i)) return -1;
  }
  return times;
}
// 只要翻好第一排,就唯一決定了全部的翻法
void sol(){
  ans = MP(INT_MAX, 1);
  for(int i=0;i<1<<M;i++){  // enumerate all status of flip
    memset(flip, 0, sizeof(flip));

    for(int j=0;j<M;j++)if((i>>j)&1)
      flip[0][j] = 1;

    a = cal();
    if(a > -1 and a < ans.X) ans = MP(a, i);
  }
  if(ans.X == INT_MAX) puts("IMPOSSIBLE");
  else {
    memset(flip, 0, sizeof(flip));

    for(int j=0;j<M;j++)if((ans.Y>>j)&1)
      flip[0][j] = 1;

    cal();
    
    for(int i=0;i<N;i++)for(int j=0;j<M;j++)
      cout << flip[i][j] << " \n"[j==M-1];
  }
}

int main(){
  init();
  sol();
}
comments powered by Disqus