Problem:
Problem C:
Median Filter
The median filter is a nonlinear digital filter used to reduce noise in images, sounds, and other kinds of signals.
It examines each sample of the input through a
window
and then emits the
median
of the samples in the win-
dow. Roughly speaking, a window is an interval that contains a target sample and its preceding and succeeding
samples; the median of a series of values is given by the middle value of the series arranged in ascending (or
descending) order.
Let us focus on a typical median filter for black-and-white raster images. The typical filter uses a 3 × 3 window,
which contains a target pixel and the eight adjacent pixels. The filter examines each pixel in turn through this
3 × 3 window, and outputs the median of the nine pixel values, i.e. the fifth lowest (or highest) pixel value, to the
corresponding pixel. We should note that the output is just given by the pixel value in majority for black-and-
white images, since there are only two possible pixel values (i.e. black and white). The figure below illustrates
how the filter works.
Note:
The colors of lightly-shaded pixels depend on outside of the region.
The edges of images need to be specially processed due to lack of the adjacent pixels. In this problem, we extends
the original images by repeating pixels on the edges as shown in the figure below. In other words, the lacked
pixels take the same values as the nearest available pixels in the original images.
Note:
The letters ‘a’ through ‘f’ indicate pixel values.
You are requested to write a program that reads images to which the filter is applied, then finds the original
images containing the greatest and smallest number of black pixels among all possible ones, and reports the
difference in the numbers of black pixels.
Input
The input contains a series of test cases.
The first line of each test case contains two integers
W
and
H
(1 ≤
W
,
H
≤ 8), which indicates the width and
height of the image respectively. Then
H
lines follow to describe the filtered image. The
i
-th line represents
the
i
-th scan line and contains exactly
W
characters, each of which is either ‘#’ (representing black) or ‘.’
(representing white).
The input is terminated by a line with two zeros.
Output
For each test case, print a line that contains the case number followed by the difference of black pixels. If there
are no original images possible for the given filtered image, print “Impossible” instead.
Obey the format as shown in the sample output.
Sample Input
5 5
#####
#####
#####
#####
#####
4 4
####
####
####
####
4 4
#...
....
....
...#
4 4
.#.#
#.#.
.#.#
#.#.
0 0
Output for the Sample Input
Case 1: 10
Case 2: 6
Case 3: 2
Case 4: Impossible

Submitted solutions:

code_snippet: // AOJ #2114 Median Filter
// 2025.5.1

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int dp_min[256][256], dp_max[256][256], ndp_min[256][256], ndp_max[256][256];

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int tc = 1;
    while (true) {
        int w, h;
        cin >> w >> h;
        if (w == 0) break;
        vector<string> g(h);
        for (int i = 0; i < h; i++) cin >> g[i];
        int M = 1 << w;
        const int INF = 1e9;

        if (h == 1) {
            int lo = INF, hi = -INF;
            for (int m = 0; m < M; m++) {
                bool ok = true;
                for (int j = 0; j < w && ok; j++) {
                    int cnt = 0;
                    for (int di = -1; di <= 1; di++)
                        for (int dj = -1; dj <= 1; dj++) {
                            int y = j + dj;
                            if (y < 0 || y >= w) y = j;
                            if ((m >> y) & 1) cnt++;
                        }
                    if ((g[0][j] == '#' && cnt < 5) || (g[0][j] == '.' && cnt > 4)) ok = false;
                }
                if (ok) {
                    int pc = __builtin_popcount(m);
                    lo = min(lo, pc);
                    hi = max(hi, pc);
                }
            }
            cout << "Case " << tc++ << ": ";
            if (lo == INF) cout << "Impossible" << endl;
            else cout << hi - lo << endl;
            continue;
        }

        for (int a = 0; a < M; a++)
            for (int b = 0; b < M; b++)
                dp_min[a][b] = INF, dp_max[a][b] = -INF;

        for (int a = 0; a < M; a++) for (int b = 0; b < M; b++) {
            bool ok = true;
            for (int j = 0; j < w && ok; j++) {
                int c = 0;
                for (int di = -1; di <= 1; di++) {
                    int r = (di <= 0 ? a : b);
                    for (int dj = -1; dj <= 1; dj++) {
                        int y = j + dj;
                        if (y < 0 || y >= w) y = j;
                        if ((r >> y) & 1) c++;
                    }
                }
                if ((g[0][j] == '#' && c < 5) || (g[0][j] == '.' && c > 4)) ok = false;
            }
            if (ok) {
                int s = __builtin_popcount(a) + __builtin_popcount(b);
                dp_min[a][b] = dp_max[a][b] = s;
            }
        }

        for (int i = 2; i < h; i++) {
            for (int a = 0; a < M; a++)
                for (int b = 0; b < M; b++)
                    ndp_min[a][b] = INF, ndp_max[a][b] = -INF;

            for (int p = 0; p < M; p++) for (int q = 0; q < M; q++) {
                if (dp_min[p][q] > dp_max[p][q]) continue;
                for (int r = 0; r < M; r++) {
                    bool ok = true;
                    for (int j = 0; j < w && ok; j++) {
                        int c = 0;
                        for (int di = -1; di <= 1; di++) {
                            int row = (di < 0 ? p : (di == 0 ? q : r));
                            for (int dj = -1; dj <= 1; dj++) {
                                int y = j + dj;
                                if (y < 0 || y >= w) y = j;
                                if ((row >> y) & 1) c++;
                            }
                        }
                        char t = g[i - 1][j];
                        if ((t == '#' && c < 5) || (t == '.' && c > 4)) ok = false;
                    }
                    if (ok) {
                        int s = __builtin_popcount(r);
                        ndp_min[q][r] = min(ndp_min[q][r], dp_min[p][q] + s);
                        ndp_max[q][r] = max(ndp_max[q][r], dp_max[p][q] + s);
                    }
                }
            }
            for (int a = 0; a < M; a++)
                for (int b = 0; b < M; b++)
                    dp_min[a][b] = ndp_min[a][b], dp_max[a][b] = ndp_max[a][b];
        }

        int lo = INF, hi = -INF;
        for (int p = 0; p < M; p++) for (int q = 0; q < M; q++) {
            if (dp_min[p][q] > dp_max[p][q]) continue;
            bool ok = true;
            for (int j = 0; j < w && ok; j++) {
                int c = 0;
                for (int di = -1; di <= 1; di++) {
                    int row = (di < 0 ? p : q);
                    for (int dj = -1; dj <= 1; dj++) {
                        int y = j + dj;
                        if (y < 0 || y >= w) y = j;
                        if ((row >> y) & 1) c++;
                    }
                }
                char t = g[h - 1][j];
                if ((t == '#' && c < 5) || (t == '.' && c > 4)) ok = false;
            }
            if (ok) {
                lo = min(lo, dp_min[p][q]);
                hi = max(hi, dp_max[p][q]);
            }
        }
        cout << "Case " << tc++ << ": ";
        if (lo == INF) cout << "Impossible" << endl;
        else cout << hi - lo << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 3730
memory_kb: 4372
final_rank: 3

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;

int H, W;

vector<pair<int, int>>get_z(int now_x,int now_y) {
	int rest=W+1;
	vector<pair<int,int>>z;
	while (rest--) {
		if(!now_x&&!now_y)break;
		if (!now_x) {
			now_y--;
			now_x=W-1;
		}
		else {
			now_x--;
		}
		z.push_back(make_pair(now_x, now_y));
	}
	reverse(z.begin(),z.end());
	return z;
}

bool connect(pair<int, int>&l, pair<int, int>&r) {
	return abs(l.first-r.first)<=1&&abs(l.second-r.second)<=1;
}

int main() {
	int case_cnt=0;
	while (cin >> W>>H) {
		if(!H)break;
		case_cnt++;
		vector<vector<int>>field(H,vector<int>(W));
		for (int i = 0; i < H; ++i) {
			string st;cin>>st;
			for (int j = 0; j < W; ++j) {
				field[i][j]=st[j]=='#';
			}
		}

		map<vector<pair<int,int>>,pair<int,int>>prevs;
		prevs.emplace(vector<pair<int,int>>(0),make_pair(0,0));


		int dx8[8] = { -1,-1,-1, 0, 1, 1, 1, 0 };
		int dy8[8] = { -1, 0, 1, 1, 1, 0,-1,-1 };
		for (int now_y = 0; now_y < H; ++now_y) {
			for (int now_x = 0; now_x < W; ++now_x) {
				pair<int,int>now(now_x,now_y);
				map<vector<pair<int,int>>,pair<int,int>>next_prevs;
				vector<pair<int,int>>zahyous(get_z(now_x,now_y));
				for (auto&& aprev : prevs) {
					const int prev_min_cnt=aprev.second.first;
					const int prev_max_cnt=aprev.second.second;
					for (int now_black = 0; now_black < 2; ++now_black) {
						vector<pair<int,int>> next_p(aprev.first);
						//black

						int now_num=now_black;
						{
							bool x_hasi=now_x==0||now_x==W-1;
							bool y_hasi=now_y==0||now_y==H-1;
							if (x_hasi&&y_hasi) {
								if(H==1||W==1)now_num*=6;
								else now_num*=4;
							}
							else if (x_hasi || y_hasi) {
								
								if(x_hasi&&now_x==0&&now_x==W-1)now_num*=3;
								else if(y_hasi&&now_y==0&&now_y==H-1)now_num*=3;
								else now_num*=2;
							}
						}
						for (int i = 0; i < zahyous.size(); ++i) {

							int bai=1;
							if(now_x==0&&zahyous[i].first==0)bai++;
							if(now_x==W-1&&zahyous[i].first==W-1)bai++;
							if(now_y==0&&zahyous[i].second==0)bai++;
							if(now_y==H-1&&zahyous[i].second==H-1)bai++;
							if (connect(zahyous[i], now)) {
								if (now_black) {
									next_p[i].second+=bai;
								}
								if (next_p[i].first) {
									now_num+=bai;
								}
							}
						}
						

						bool ok = true;
						if (zahyous.size() == W + 1) {
							bool f_black=field[zahyous[0].second][zahyous[0].first]==1;
							int num=next_p[0].second;
							if ((f_black ^ (num >= 5))) {
								ok=false;
							}
						}

						if (ok) {
							
							if (zahyous.size() == W + 1) {
								next_p.erase(next_p.begin());
							}
							next_p.push_back(make_pair(now_black, now_num));
							for (int i = 0; i < next_p.size(); ++i) {
								next_p[i].second=min(5,next_p[i].second);
							}
							if(next_p.size()==W+1&&next_p[0].second<3)next_p[0].second=0;
							if (next_prevs.find(next_p) == next_prevs.end()) {
								next_prevs[next_p]=make_pair(prev_min_cnt+now_black,prev_max_cnt+now_black);
							}
							else {
								next_prevs[next_p]=make_pair(
									min(next_prevs[next_p].first,prev_min_cnt+now_black),
									max(next_prevs[next_p].second,prev_max_cnt+now_black));
							}
						}
					}
				}
				prevs=move(next_prevs);
				next_prevs.clear();
			}
		}
		int amin=1000;
		int amax=-1;
		{
			vector<pair<int, int>>zahyous(get_z(0, H));
			for (auto&& pr : prevs) {
				bool valid = true;
				for (int i = 0; i < pr.first.size(); ++i) {
					bool f_black=field[zahyous[i].second][zahyous[i].first]==1;
					int num=pr.first[i].second;
					if (f_black ^ (num >= 5)) {
						valid=false;
					}
				}
				if (valid) {
					amin=min(amin,pr.second.first);
					amax=max(amax,pr.second.second);
				}
			}
		}

		cout<<"Case "<<case_cnt<<": ";
		if (amin == 1000) {
			cout<<"Impossible"<<endl;
		}
		else {
			cout<<amax-amin<<endl;
		}
		
	}
	return 0;
}
accuracy: 1
time_ms: 7400
memory_kb: 23388
final_rank: 8

code_snippet: #include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

const int INF = INT_MAX / 4;

int h, w;
vector<string> s;

int main()
{
    for(int d=1; ; ++d){
        cin >> w >> h;
        if(h == 0)
            return 0;

        if(w == 1)
            swap(h, w);

        s.assign(h, string(w, ' '));
        for(int i=0; i<h; ++i){
            for(int j=0; j<w; ++j){
                cin >> s[i][j];
            }
        }

        if(h == 1 && w == 1){
            cout << "Case " << d << ": 0" << endl;
            continue;
        }

        vector<pair<int, int> > dp(1<<(2*w+2), make_pair(INF, -INF));
        for(int i=0; i<(1<<w); ++i){
            bitset<32> bs = i;
            int black = bs.count();
            bs <<= w;
            bs |= i;
            dp[bs.to_ulong()] = make_pair(black, black);
        }

        for(int y=0; y<h; ++y){
            for(int x=0; x<w; ++x){
                vector<pair<int, int> > next(1<<(2*w+2), make_pair(INF, -INF));
                for(int a=0; a<(1<<(2*w+2)); ++a){
                    if(dp[a].first == INF)
                        continue;

                    for(int b=0; b<2; ++b){
                        bitset<32> bs = a;
                        bs <<= 1;
                        bs |= b;
                        if(y == h-1 && (bs[0] ^ bs[w]))
                            continue;

                        bool ng = false;

                        if(x == 1){ // 左端
                            int black = 0;
                            for(int i=0; i<3; ++i){
                                for(int j=0; j<2; ++j){
                                    if(bs[i*w+j])
                                        black += j + 1;
                                }
                            }
                            if((black >= 5) ^ (s[y][x-1] == '#'))
                                ng = true;
                        }

                        if(x > 1){ // 中央
                            int black = 0;
                            for(int i=0; i<3; ++i){
                                for(int j=0; j<3; ++j){
                                    if(bs[i*w+j])
                                        ++ black;
                                }
                            }
                            if((black >= 5) ^ (s[y][x-1] == '#'))
                                ng = true;
                        }

                        if(x == w-1){ // 右端
                            int black = 0;
                            for(int i=0; i<3; ++i){
                                for(int j=0; j<2; ++j){
                                    if(bs[i*w+j])
                                        black += 2 - j;
                                }
                            }
                            if((black >= 5) ^ (s[y][x] == '#'))
                                ng = true;
                        }

                        if(!ng){
                            bs &= (1<<(2*w+2)) - 1;
                            if(y < h-1){
                                next[bs.to_ulong()].first = min(next[bs.to_ulong()].first, dp[a].first + b);
                                next[bs.to_ulong()].second = max(next[bs.to_ulong()].second, dp[a].second + b);
                            }else{
                                next[bs.to_ulong()].first = min(next[bs.to_ulong()].first, dp[a].first);
                                next[bs.to_ulong()].second = max(next[bs.to_ulong()].second, dp[a].second);
                            }
                        }
                    }
                }
                dp.swap(next);
            }
        }

        int minBlack = INF;
        int maxBlack = -INF;
        for(int i=0; i<(1<<(2*w+2)); ++i){
            minBlack = min(minBlack, dp[i].first);
            maxBlack = max(maxBlack, dp[i].second);
        }

        if(minBlack == INF)
            cout << "Case " << d << ": Impossible" << endl;
        else
            cout << "Case " << d << ": " << (maxBlack - minBlack) << endl;
    }
}
accuracy: 1
time_ms: 1310
memory_kb: 5304
final_rank: 2

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

unsigned int table[256];
int ldp[8][1 << 8][1 << 8];
int udp[8][1 << 8][1 << 8];

int interp(int bits, int w){
	bits = (bits << 1) | (bits & 1);
	return bits | ((bits & (1 << w)) << 1);
}

int main(){
	for(int i = 0; i < 256; ++i){
		unsigned int x = 0;
		for(int j = 0; j < 8; ++j){
			if(i & (1 << j)){ x |= (1 << (j * 4)); }
		}
		table[i] = x;
	}
	int caseNum = 1;
	while(true){
		int H, W;
		cin >> W >> H;
		if(H == 0 && W == 0){ break; }
		vector<string> simage(H);
		for(int i = 0; i < H; ++i){ cin >> simage[i]; }
		vector<int> image(max(H, W));
		if(H >= W){
			for(int i = 0; i < H; ++i){
				for(int j = 0; j < W; ++j){
					image[i] |= (simage[i][j] == '#') << j;
				}
			}
		}else{
			swap(H, W);
			for(int i = 0; i < W; ++i){
				for(int j = 0; j < H; ++j){
					image[j] |= (simage[i][j] == '#') << i;
				}
			}
		}
		for(int i = 0; i < H; ++i){
			for(int j = 0; j < (1 << W); ++j){
				for(int k = 0; k < (1 << W); ++k){
					ldp[i][j][k] = H * W + 1;
					udp[i][j][k] = -1;
				}
			}
		}
		int mask = (1 << W) - 1;
		for(int i = 0; i < (1 << W); ++i){
			int r0 = interp(i, W), r1 = r0;
			for(int j = 0; j < (1 << W); ++j){
				int r2 = interp(j, W), numBlack = __builtin_popcount(i);
				unsigned int c = 0;
				c += table[(r0 >> 0) & mask];
				c += table[(r0 >> 1) & mask];
				c += table[(r0 >> 2) & mask];
				c += table[(r1 >> 0) & mask];
				c += table[(r1 >> 1) & mask];
				c += table[(r1 >> 2) & mask];
				c += table[(r2 >> 0) & mask];
				c += table[(r2 >> 1) & mask];
				c += table[(r2 >> 2) & mask];
				c = ((c + 0x33333333) & 0x88888888) >> 3;
				if(c == table[image[0]]){
					ldp[0][i][j] = udp[0][i][j] = numBlack;
				}
			}
		}
		for(int i = 1; i < H - 1; ++i){
			for(int j0 = 0; j0 < (1 << W); ++j0){
				int r0 = interp(j0, W);
				for(int j1 = 0; j1 < (1 << W); ++j1){
					int r1 = interp(j1, W), numBlack = __builtin_popcount(j1);
					if(udp[i - 1][j0][j1] < 0){ continue; }
					for(int j2 = 0; j2 < (1 << W); ++j2){
						int r2 = interp(j2, W);
						unsigned int c = 0;
						c += table[(r0 >> 0) & mask];
						c += table[(r0 >> 1) & mask];
						c += table[(r0 >> 2) & mask];
						c += table[(r1 >> 0) & mask];
						c += table[(r1 >> 1) & mask];
						c += table[(r1 >> 2) & mask];
						c += table[(r2 >> 0) & mask];
						c += table[(r2 >> 1) & mask];
						c += table[(r2 >> 2) & mask];
						c = ((c + 0x33333333) & 0x88888888) >> 3;
						if(c == table[image[i]]){
							int lower = ldp[i - 1][j0][j1] + numBlack;
							int upper = udp[i - 1][j0][j1] + numBlack;
							ldp[i][j1][j2] = min(ldp[i][j1][j2], lower);
							udp[i][j1][j2] = max(udp[i][j1][j2], upper);
						}
					}
				}
			}
		}
		int minval = H * W + 1, maxval = -1;
		if(H == 1){
			for(int i = 0; i < (1 << W); ++i){
				minval = min(minval, ldp[0][i][i]);
				maxval = max(maxval, udp[0][i][i]);
			}
		}else{
			for(int i = 0; i < (1 << W); ++i){
				int r0 = interp(i, W);
				for(int j = 0; j < (1 << W); ++j){
					int r1 = interp(j, W), r2 = r1;
					if(udp[H - 2][i][j] < 0){ continue; }
					int numBlack = __builtin_popcount(j);
					unsigned int c = 0;
					c += table[(r0 >> 0) & mask];
					c += table[(r0 >> 1) & mask];
					c += table[(r0 >> 2) & mask];
					c += table[(r1 >> 0) & mask];
					c += table[(r1 >> 1) & mask];
					c += table[(r1 >> 2) & mask];
					c += table[(r2 >> 0) & mask];
					c += table[(r2 >> 1) & mask];
					c += table[(r2 >> 2) & mask];
					c = ((c + 0x33333333) & 0x88888888) >> 3;
					if(c == table[image[H - 1]]){
						int lower = ldp[H - 2][i][j] + numBlack;
						int upper = udp[H - 2][i][j] + numBlack;
						minval = min(minval, lower);
						maxval = max(maxval, upper);
					}
				}
			}
		}
		cout << "Case " << caseNum++ << ": ";
		if(maxval < 0){
			cout << "Impossible" << endl;
		}else{
			cout << maxval - minval << endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 620
memory_kb: 5028
final_rank: 1

code_snippet: #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()

const int N = 8;
const int inf = (1<<20);
char m[N][N];

inline int getval(int c,int j,int bit){
  if      (j == -1)j=0;
  else if (j ==  c)j=c-1;
  return (bit&(1<<j)) != 0;
}

inline int checkij(int r,int c,int i,int j,int bit0,int bit1,int bit2){
  int ret=0;
  int bit=0;
  //bit0
  if (i-1 < 0)bit=bit1;
  else        bit=bit0;
  REP(k,-1,2)ret+=getval(c,j+k,bit);

  //bit1
  bit=bit1;
  REP(k,-1,2)ret+=getval(c,j+k,bit);

  //bit2
  if (i+1 == r)bit=bit1;
  else         bit=bit2;
  REP(k,-1,2)ret+=getval(c,j+k,bit);
  return ret;
}

inline bool isvalid(int r,int c,int now,int bit0,int bit1,int bit2){
  rep(j,c){
    int cnt=checkij(r,c,now-1,j,bit0,bit1,bit2);
    if ((m[now-1][j] == '#'&&cnt>=5) ||
	(m[now-1][j] == '.'&&cnt<5 ));
    else return false;
  }
  return true;
}

int dp[1<<N][1<<N][N];
int dp2[1<<N][1<<N][N];
//int bitcount[1<<N];
#define bitcount(i) (__builtin_popcount(i))

void solve(int r,int c,int bit0,int bit1,int now){
  if (now == r){
    if (isvalid(r,c,now,bit0,bit1,0)){
      dp[ bit0][bit1][now-1]=bitcount(bit1);
      dp2[bit0][bit1][now-1]=bitcount(bit1);
    }else {
      dp[ bit0][bit1][now-1] =-inf;
      dp2[bit0][bit1][now-1]= inf;
    }
    return;
  }
  int &ret= dp[ bit0][bit1][now-1];
  int &ret2=dp2[bit0][bit1][now-1];
  if (ret == -2*inf ){
    ret=-inf;
    ret2=inf;
    rep(i,(1<<c)){
      if (isvalid(r,c,now,bit0,bit1,i)){
	solve(r,c,bit1,i,now+1);
	if (dp[bit1][i][now] != -inf){
	  ret =max(ret, dp[bit1][i][now]+bitcount(bit1));
	  ret2=min(ret2,dp2[bit1][i][now]+bitcount(bit1));
	}
      }
    }
  }
  return;
}

main(){
  //rep(i,(1<<N))bitcount[i]=__builtin_popcount(i);
  int c,r,tc=1;
  while(cin>>c>>r && r){
    cout <<"Case " << tc++ << ": ";
    rep(i,r)cin>>m[i];
    rep(i,(1<<c)){
      rep(j,(1<<c)){
	rep(k,r){
	  dp[i][j][k]=-2*inf;
	  //dp2[i][j][k]=2*inf;
	}
      }
    }
    int maxi=-2*inf,mini=inf;
    rep(i,(1<<c)){
      solve(r,c,0,i,1);
      if (dp[0][i][0] >= 0){
	maxi=max(maxi,dp[0][i][0]);
	mini=min(mini,dp2[0][i][0]);
      }
    }

    if (maxi < 0){
      cout <<"Impossible" << endl;
      continue;
    }else  cout << maxi-mini << endl;
  }
  return false;
}



/*
void test(){
  int bit0=17,bit1=14,bit2=24;
  int r=3,c=5;
  rep(j,c)cout << checkij(r,c,0,j,0,bit0,bit1)<<" ";cout << endl;
  rep(j,c)cout << checkij(r,c,1,j,bit0,bit1,bit2)<<" ";cout << endl;
  rep(j,c)cout << checkij(r,c,2,j,bit1,bit2,0)<<" ";cout << endl;
}

void output(int c,int bit){
  rep(j,c){
    if ((1<<j)&bit) cout <<"#";
    else cout << ".";
  }
  cout << endl;
}

*/
accuracy: 1
time_ms: 6070
memory_kb: 4976
final_rank: 4

code_snippet: #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()

const int N = 8;
const int inf = (1<<20);
char m[N][N];

inline int getval(int c,int j,int bit){
  if      (j == -1)j=0;
  else if (j ==  c)j=c-1;
  return (bit&(1<<j)) != 0;
}

inline int checkij(int r,int c,int i,int j,int bit0,int bit1,int bit2){
  int ret=0;
  int bit=0;
  //bit0
  if (i-1 < 0)bit=bit1;
  else        bit=bit0;
  REP(k,-1,2)ret+=getval(c,j+k,bit);

  //bit1
  bit=bit1;
  REP(k,-1,2)ret+=getval(c,j+k,bit);

  //bit2
  if (i+1 == r)bit=bit1;
  else         bit=bit2;
  REP(k,-1,2)ret+=getval(c,j+k,bit);
  return ret;
}

inline bool isvalid(int r,int c,int now,int bit0,int bit1,int bit2){
  rep(j,c){
    int cnt=checkij(r,c,now-1,j,bit0,bit1,bit2);
    if ((m[now-1][j] == '#'&&cnt>=5) ||
	(m[now-1][j] == '.'&&cnt<5 ));
    else return false;
  }
  return true;
}

int dp[1<<N][1<<N][N];
int dp2[1<<N][1<<N][N];
int bitcount[1<<N];

void solve(int r,int c,int bit0,int bit1,int now){
  if (now == r){
    if (isvalid(r,c,now,bit0,bit1,0)){
      dp[ bit0][bit1][now-1]=bitcount[bit1];
      dp2[bit0][bit1][now-1]=bitcount[bit1];
    }else {
      dp[ bit0][bit1][now-1] =-inf;
      dp2[bit0][bit1][now-1]= inf;
    }
    return;
  }
  int &ret= dp[ bit0][bit1][now-1];
  int &ret2=dp2[bit0][bit1][now-1];
  if (ret == -2*inf ){
    ret=-inf;
    ret2=inf;
    rep(i,(1<<c)){
      if (isvalid(r,c,now,bit0,bit1,i)){
	solve(r,c,bit1,i,now+1);
	if (dp[bit1][i][now] != -inf){
	  ret =max(ret, dp[bit1][i][now]+bitcount[bit1]);
	  ret2=min(ret2,dp2[bit1][i][now]+bitcount[bit1]);
	}
      }
    }
  }
  return;
}

main(){
  rep(i,(1<<N))bitcount[i]=__builtin_popcount(i);
  int c,r,tc=1;
  while(cin>>c>>r && r){
    cout <<"Case " << tc++ << ": ";
    rep(i,r)cin>>m[i];
    rep(i,(1<<c)){
      rep(j,(1<<c)){
	rep(k,r){
	  dp[i][j][k]=-2*inf;
	  //dp2[i][j][k]=2*inf;
	}
      }
    }
    int maxi=-2*inf,mini=inf;
    rep(i,(1<<c)){
      solve(r,c,0,i,1);
      if (dp[0][i][0] >= 0){
	maxi=max(maxi,dp[0][i][0]);
	mini=min(mini,dp2[0][i][0]);
      }
    }

    if (maxi < 0){
      cout <<"Impossible" << endl;
      continue;
    }else  cout << maxi-mini << endl;
  }
  return false;
}



/*
void test(){
  int bit0=17,bit1=14,bit2=24;
  int r=3,c=5;
  rep(j,c)cout << checkij(r,c,0,j,0,bit0,bit1)<<" ";cout << endl;
  rep(j,c)cout << checkij(r,c,1,j,bit0,bit1,bit2)<<" ";cout << endl;
  rep(j,c)cout << checkij(r,c,2,j,bit1,bit2,0)<<" ";cout << endl;
}

void output(int c,int bit){
  rep(j,c){
    if ((1<<j)&bit) cout <<"#";
    else cout << ".";
  }
  cout << endl;
}

*/
accuracy: 1
time_ms: 6240
memory_kb: 4972
final_rank: 6

code_snippet: #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()

const int N = 8;
const int inf = (1<<20);
char m[N][N];

inline int getval(int c,int j,int bit){
  if      (j == -1)j=0;
  else if (j ==  c)j=c-1;
  return (bit&(1<<j)) != 0;
}

inline int checkij(int r,int c,int i,int j,int bit0,int bit1,int bit2){
  int ret=0;
  int bit=0;
  //bit0
  if (i-1 < 0)bit=bit1;
  else        bit=bit0;
  REP(k,-1,2)ret+=getval(c,j+k,bit);

  //bit1
  bit=bit1;
  REP(k,-1,2)ret+=getval(c,j+k,bit);

  //bit2
  if (i+1 == r)bit=bit1;
  else         bit=bit2;
  REP(k,-1,2)ret+=getval(c,j+k,bit);
  return ret;
}

inline bool isvalid(int r,int c,int now,int bit0,int bit1,int bit2){
  rep(j,c){
    int cnt=checkij(r,c,now-1,j,bit0,bit1,bit2);
    if ((m[now-1][j] == '#'&&cnt>=5) ||
	(m[now-1][j] == '.'&&cnt<5 ));
    else return false;
  }
  return true;
}

int dp[1<<N][1<<N][N];
int dp2[1<<N][1<<N][N];
int bitcount[1<<N];

void solve(int r,int c,int bit0,int bit1,int now){
  if (now == r){
    if (isvalid(r,c,now,bit0,bit1,0)){
      dp[ bit0][bit1][now-1]=bitcount[bit1];
      dp2[bit0][bit1][now-1]=bitcount[bit1];
    }else {
      dp[ bit0][bit1][now-1] =-inf;
      dp2[bit0][bit1][now-1]= inf;
    }
    return;
  }
  int &ret= dp[ bit0][bit1][now-1];
  int &ret2=dp2[bit0][bit1][now-1];
  if (ret == -2*inf ){
    ret=-inf;
    ret2=inf;
    rep(i,(1<<c)){
      if (isvalid(r,c,now,bit0,bit1,i)){
	solve(r,c,bit1,i,now+1);
	if (dp[bit1][i][now] != -inf){
	  ret =max(ret, dp[bit1][i][now]+bitcount[bit1]);
	}
	if (dp2[bit1][i][now] != inf){
	  ret2=min(ret2,dp2[bit1][i][now]+bitcount[bit1]);
	}
      }
    }
  }
  return;
}

main(){
  rep(i,(1<<N))bitcount[i]=__builtin_popcount(i);
  int c,r,tc=1;
  while(cin>>c>>r && r){
    cout <<"Case " << tc++ << ": ";
    rep(i,r)cin>>m[i];
    rep(i,(1<<c)){
      rep(j,(1<<c)){
	rep(k,r){
	  dp[i][j][k]=-2*inf;
	  //dp2[i][j][k]=2*inf;
	}
      }
    }
    int maxi=-2*inf,mini=inf;
    rep(i,(1<<c)){
      solve(r,c,0,i,1);
      if (dp[0][i][0] >= 0)maxi=max(maxi,dp[0][i][0]);
      if (dp2[0][i][0] != inf)mini=min(mini,dp2[0][i][0]);
    }

    if (maxi < 0){
      cout <<"Impossible" << endl;
      continue;
    }else  cout << maxi-mini << endl;
  }
  return false;
}



/*
void test(){
  int bit0=17,bit1=14,bit2=24;
  int r=3,c=5;
  rep(j,c)cout << checkij(r,c,0,j,0,bit0,bit1)<<" ";cout << endl;
  rep(j,c)cout << checkij(r,c,1,j,bit0,bit1,bit2)<<" ";cout << endl;
  rep(j,c)cout << checkij(r,c,2,j,bit1,bit2,0)<<" ";cout << endl;
}

void output(int c,int bit){
  rep(j,c){
    if ((1<<j)&bit) cout <<"#";
    else cout << ".";
  }
  cout << endl;
}

*/
accuracy: 1
time_ms: 6230
memory_kb: 4976
final_rank: 5

code_snippet: #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()

const int N = 8;
const int inf = (1<<20);
char m[N][N];

inline int getval(int c,int j,int bit){
  if      (j == -1)j=0;
  else if (j ==  c)j=c-1;
  return (bit&(1<<j)) != 0;
}

inline int checkij(int r,int c,int i,int j,int bit0,int bit1,int bit2){
  int ret=0;
  int bit=0;
  //bit0
  if (i-1 < 0)bit=bit1;
  else        bit=bit0;
  REP(k,-1,2)ret+=getval(c,j+k,bit);

  //bit1
  bit=bit1;
  REP(k,-1,2)ret+=getval(c,j+k,bit);

  //bit2
  if (i+1 == r)bit=bit1;
  else         bit=bit2;
  REP(k,-1,2)ret+=getval(c,j+k,bit);
  return ret;
}

inline bool isvalid(int r,int c,int now,int bit0,int bit1,int bit2){
  rep(j,c){
    int cnt=checkij(r,c,now-1,j,bit0,bit1,bit2);
    if ((m[now-1][j] == '#'&&cnt>=5) ||
	(m[now-1][j] == '.'&&cnt<5 ));
    else return false;
  }
  return true;
}

int dp[1<<N][1<<N][N];
int dp2[1<<N][1<<N][N];
int bitcount[1<<N];

int solvemax(int r,int c,int bit0,int bit1,int now){
  if (now == r){
    return isvalid(r,c,now,bit0,bit1,0)?bitcount[bit1]:-inf;
  }
  int &ret=dp[bit0][bit1][now-1];
  if (ret == -2*inf){
    //ret=bitcount[bit1];
    ret=-inf;
    rep(i,(1<<c)){
      if (isvalid(r,c,now,bit0,bit1,i)){
	ret=max(ret,solvemax(r,c,bit1,i,now+1)+bitcount[bit1]);
      }
    }
  }
  return ret;
}


int solvemin(int r,int c,int bit0,int bit1,int now){
  if (now == r){
    return isvalid(r,c,now,bit0,bit1,0)?bitcount[bit1]:inf;
  }
  int &ret=dp2[bit0][bit1][now-1];
  if (ret == 2*inf){
    ret=inf;
    rep(i,(1<<c)){
      if (isvalid(r,c,now,bit0,bit1,i)){
	ret=min(ret,solvemin(r,c,bit1,i,now+1)+bitcount[bit1]);
      }
    }
  }
  return ret;
}

void solve(int r,int c,int bit0,int bit1,int now){
  if (now == r){
    if (isvalid(r,c,now,bit0,bit1,0)){
      dp[ bit0][bit1][now-1]=bitcount[bit1];
      dp2[bit0][bit1][now-1]=bitcount[bit1];
    }else {
      dp[ bit0][bit1][now-1] =-inf;
      dp2[bit0][bit1][now-1]= inf;
    }
    return;
  }
  int &ret= dp[ bit0][bit1][now-1];
  int &ret2=dp2[bit0][bit1][now-1];
  if (ret == -2*inf ){
    ret=-inf;
    ret2=inf;
    rep(i,(1<<c)){
      if (isvalid(r,c,now,bit0,bit1,i)){
	solve(r,c,bit1,i,now+1);
	if (dp[bit1][i][now] != -inf){
	  ret =max(ret, dp[bit1][i][now]+bitcount[bit1]);
	}
	if (dp2[bit1][i][now] != inf){
	  ret2=min(ret2,dp2[bit1][i][now]+bitcount[bit1]);
	}
      }
    }
  }
  return;
}

/*
main(){
  rep(i,(1<<N))bitcount[i]=__builtin_popcount(i);
  int c,r,tc=1;
  while(cin>>c>>r && r){
    cout <<"Case " << tc++ << ": ";
    rep(i,r)cin>>m[i];
    rep(i,(1<<c)){
      rep(j,(1<<c)){
	rep(k,r){
	  dp[i][j][k]=-2*inf;
	  dp2[i][j][k]=2*inf;
	}
      }
    }
    //rep(i,(1<<c))rep(j,(1<<c))rep(k,r)dp2[i][j][k]=2*inf;
    int maxi=-2*inf,mini=inf;
    rep(i,(1<<c)){
      maxi=max(maxi,solvemax(r,c,0,i,1));
    }

    if (maxi < 0){
      cout <<"Impossible" << endl;
      continue;
    }//else  cout << maxi-mini << endl;
    //cout <<  mini <<" " << maxi << endl;

    //rep(i,(1<<c))rep(j,(1<<c))rep(k,r)dp[i][j][k]=2*inf;
    mini=inf;
    rep(i,(1<<c)){
      //cout << "huga " << i<<" "<< solvemin(r,c,0,i,1) << endl;
      mini=min(mini,solvemin(r,c,0,i,1));
    }
    //cout <<"true " << mini << endl;
    cout << maxi-mini << endl;
  }
  return false;
}
*/


main(){
  rep(i,(1<<N))bitcount[i]=__builtin_popcount(i);
  int c,r,tc=1;
  while(cin>>c>>r && r){
    cout <<"Case " << tc++ << ": ";
    rep(i,r)cin>>m[i];
    rep(i,(1<<c)){
      rep(j,(1<<c)){
	rep(k,r){
	  dp[i][j][k]=-2*inf;
	  dp2[i][j][k]=2*inf;
	}
      }
    }
    int maxi=-2*inf,mini=inf;
    rep(i,(1<<c)){
      solve(r,c,0,i,1);
      if (dp[0][i][0] >= 0)maxi=max(maxi,dp[0][i][0]);
      //cout << "hoge " << i<<" " << dp2[0][i][0] << endl;
      if (dp2[0][i][0] != inf)mini=min(mini,dp2[0][i][0]);
    }

    if (maxi < 0){
      cout <<"Impossible" << endl;
      continue;
    }else  cout << maxi-mini << endl;

    /*
    mini=inf;
    rep(i,(1<<c)){
      mini=min(mini,solvemin(r,c,0,i,1));
    }
    cout << maxi-mini << endl;
    */
  }
  return false;
}



/*
void test(){
  int bit0=17,bit1=14,bit2=24;
  int r=3,c=5;
  rep(j,c)cout << checkij(r,c,0,j,0,bit0,bit1)<<" ";cout << endl;
  rep(j,c)cout << checkij(r,c,1,j,bit0,bit1,bit2)<<" ";cout << endl;
  rep(j,c)cout << checkij(r,c,2,j,bit1,bit2,0)<<" ";cout << endl;
}

void output(int c,int bit){
  rep(j,c){
    if ((1<<j)&bit) cout <<"#";
    else cout << ".";
  }
  cout << endl;
}

*/
accuracy: 1
time_ms: 6250
memory_kb: 4980
final_rank: 7