Problem:
Problem E:
Black Force
A dam construction project was designed around an area called Black Force. The area is surrounded by
mountains and its rugged terrain is said to be very suitable for constructing a dam.
However, the project is now almost pushed into cancellation by a strong protest campaign started by the
local residents. Your task is to plan out a compromise proposal. In other words, you must find a way to
build a dam with sufficient capacity, without destroying the inhabited area of the residents.
The map of Black Force is given as
H
×
W
cells (0 <
H
,
W
≤ 20). Each cell
h
i, j
is a positive integer
representing the height of the place. The dam can be constructed at a connected region surrounded
by higher cells, as long as the region contains neither the outermost cells nor the inhabited area of the
residents. Here, a region is said to be connected if one can go between any pair of cells in the region
by following a sequence of left-, right-, top-, or bottom-adjacent cells without leaving the region. The
constructed dam can store water up to the height of the lowest surrounding cell. The capacity of the dam
is the maximum volume of water it can store. Water of the depth of 1 poured to a single cell has the
volume of 1.
The important thing is that, in the case it is difficult to build a sufficient large dam, it is allowed to
choose (at most) one cell and do groundwork to increase the height of the cell by 1 unit. Unfortunately,
considering the protest campaign, groundwork of larger scale is impossible. Needless to say, you cannot
do the groundwork at the inhabited cell.
Given the map, the required capacity, and the list of cells inhabited, please determine whether it is possible
to construct a dam.
Input
The input consists of multiple data sets. Each data set is given in the following format:
H W C R
h
1,1
h
1,2
. . .
h
1,
W
...
h
H
,1
h
H
,2
. . .
h
H
,
W
y
1
x
1
...
y
R
x
R
H
and
W
is the size of the map.
is the required capacity.
R
(0 <
R
<
H
×
W
) is the number of cells
inhabited. The following
H
lines represent the map, where each line contains
W
numbers separated by
space. Then, the
R
lines containing the coordinates of inhabited cells follow. The line “
y x
” means that
the cell
h
y,x
is inhabited.
The end of input is indicated by a line “0 0 0 0”. This line should not be processed.
Output
For each data set, print “Yes” if it is possible to construct a dam with capacity equal to or more than
C
.
Otherwise, print “No”.
Sample Input
4 4 1 1
2 2 2 2
2 1 1 2
2 1 1 2
2 1 2 2
1 1
4 4 1 1
2 2 2 2
2 1 1 2
2 1 1 2
2 1 2 2
2 2
4 4 1 1
2 2 2 2
2 1 1 2
2 1 1 2
2 1 1 2
1 1
3 6 6 1
1 6 7 1 7 1
5 1 2 8 1 6
1 4 3 1 5 1
1 4
5 6 21 1
1 3 3 3 3 1
3 1 1 1 1 3
3 1 1 3 2 2
3 1 1 1 1 3
1 3 3 3 3 1
3 4
0 0 0 0
Output for the Sample Input
Yes
No
No
No
Yes

Submitted solutions:

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <algorithm>
#include <numeric>
#include <utility>
#include <complex>
#include <functional>

using namespace std;

/* constant */

const int MAX_H = 20;
const int MAX_W = 20;
const int MAX_R = MAX_H * MAX_W;
const int INF = 1 << 30;

const int dxs[] = { 1, 0, -1, 0};
const int dys[] = { 0, -1, 0, 1};

/* typedef */

typedef vector<int> vi;
typedef pair<int, int> pii;

/* global variables */

int h, w, c, r;
int hgts[MAX_H][MAX_W];
pii ihpts[MAX_R];
bool ihbs[MAX_H][MAX_W], rgs[MAX_H][MAX_W], used[MAX_H][MAX_W];
int nrg;

/* subroutines */

void ngrgs(int y0, int x0) {
    if (! rgs[y0][x0])
        return;

    queue<pii> q;
    q.push(pii(y0, x0));
    rgs[y0][x0] = false;
    nrg--;

    while (! q.empty()) {
        pii u = q.front();
        q.pop();
        int &uy = u.first;
        int &ux = u.second;
        int uh = hgts[uy][ux];

        for (int di = 0; di < 4; di++) {
            int vy = uy + dys[di];
            int vx = ux + dxs[di];

            if (vy >= 0 && vy < h && vx >= 0 && vx < w &&
                    rgs[vy][vx] && hgts[vy][vx] >= uh) {
                rgs[vy][vx] = false;
                nrg--;
                q.push(pii(vy, vx));
            }
        }
    }
}

bool dam() {
    nrg = w * h;
    memset(rgs, true, sizeof(rgs));

    for (int y0 = 0; y0 < h; y0++) {
        ngrgs(y0, 0);
        ngrgs(y0, w - 1);
    }

    for (int x0 = 0; x0 < w; x0++) {
        ngrgs(0, x0);
        ngrgs(h - 1, x0);
    }

    for (int i = 0; i < r; i++)
        ngrgs(ihpts[i].first, ihpts[i].second);

    if (false) {
        for (int y = 0; y < h; y++) {
            for (int x = 0; x < w; x++)
                cout << rgs[y][x];

            cout << endl;
        }
    }

    while (nrg) {
        int y0 = 0, x0 = 0;

        while (! rgs[y0][x0])
            if (++x0 >= w)
                x0 = 0, y0++;

        int min_wl = INF, y1, x1;
        memset(used, false, sizeof(used));
        used[y0][x0] = true;
        queue<pii> q;
        q.push(pii(y0, x0));

        while (! q.empty()) {
            pii u = q.front();
            q.pop();
            int &uy = u.first;
            int &ux = u.second;

            for (int di = 0; di < 4; di++) {
                int vy = uy + dys[di];
                int vx = ux + dxs[di];

                if (! rgs[vy][vx]) {
                    if (min_wl > hgts[vy][vx]) {
                        min_wl = hgts[vy][vx];
                        y1 = uy, x1 = ux;
                    }
                } else if (! used[vy][vx]) {
                    used[vy][vx] = true;
                    q.push(pii(vy, vx));
                }
            }
        }

        int wv = min_wl - hgts[y1][x1];
        memset(used, false, sizeof(used));
        used[y1][x1] = true;
        queue<pii> q0;
        q0.push(pii(y1, x1));

        while (! q0.empty()) {
            pii u = q0.front();
            q0.pop();
            int &uy = u.first;
            int &ux = u.second;

            for (int di = 0; di < 4; di++) {
                int vy = uy + dys[di];
                int vx = ux + dxs[di];

                if (rgs[vy][vx] && ! used[vy][vx] && min_wl > hgts[vy][vx]) {
                    wv += min_wl - hgts[vy][vx];
                    used[vy][vx] = true;
                    q0.push(pii(vy, vx));
                }
            }
        }

        //printf("wv=%d\n", wv);
        if (wv >= c)
            return true;

        ngrgs(y1, x1);
    }

    return false;
}

/* main */

int main() {
    for (;;) {
        cin >> h >> w >> c >> r;

        if (h == 0)
            break;

        for (int y = 0; y < h; y++)
            for (int x = 0; x < w; x++)
                cin >> hgts[y][x];

        memset(ihbs, false, sizeof(ihbs));

        for (int i = 0; i < r; i++) {
            int y, x;
            cin >> y >> x;
            y--, x--;
            ihpts[i].first = y;
            ihpts[i].second = x;
            ihbs[y][x] = true;
        }

        bool ok = dam();

        for (int y = 0; ! ok && y < h; y++)
            for (int x = 0; ! ok && x < w; x++)
                if (! ihbs[y][x]) {
                    hgts[y][x]++;
                    ok = dam();
                    //printf("(%d,%d)=%d\n", y, x, ok);
                    hgts[y][x]--;
                }

        cout << (ok ? "Yes" : "No") << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 3220
final_rank: 6

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 21


int H,W,CAP,num_resident;
int diff_row[4] = {-1,0,0,1},diff_col[4] = {0,-1,1,0};
int height[NUM][NUM],pool;
bool exist[NUM][NUM],visited[NUM][NUM],Area_FLG;
set<int> SET;

bool rangeCheck(int row,int col){
	if(row >= 0 && row <= H-1 && col >= 0 && col <= W-1)return true;
	else{
		return false;
	}
}

void searchArea(int row,int col,int base_height){

	visited[row][col] = true;
	pool += base_height-height[row][col];

	if(row == 0 || row == H-1 || col == 0 || col == W-1 || exist[row][col] == true){
		Area_FLG = false;
	}
	int next_row,next_col;
	for(int i = 0; i < 4; i++){
		next_row = row+diff_row[i];
		next_col = col+diff_col[i];
		if(rangeCheck(next_row,next_col) == false || visited[next_row][next_col] == true ||
				height[next_row][next_col] >= base_height)continue;

		searchArea(next_row,next_col,base_height);
	}
}

bool is_ok(int base_height){

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++)visited[row][col] = false;
	}
	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(visited[row][col] == true || height[row][col] >= base_height)continue;

			pool = 0;
			Area_FLG = true;

			searchArea(row,col,base_height);

			if(Area_FLG == true && pool >= CAP){
				return true;
			}
		}
	}
	return false;
}

void func(){

	SET.clear();

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			scanf("%d",&height[row][col]);
			SET.insert(height[row][col]);
		}
	}
	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++)exist[row][col] = false;
	}

	int tmp_row,tmp_col;
	for(int loop = 0; loop < num_resident; loop++){
		scanf("%d %d",&tmp_row,&tmp_col);
		tmp_row--;
		tmp_col--;
		exist[tmp_row][tmp_col] = true;
	}

	int tmp_height;
	for(auto it = SET.begin(); it != SET.end(); it++) {

		tmp_height = *it;

		if(is_ok(tmp_height)){
			printf("Yes\n");
			return;
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(exist[row][col])continue;

			height[row][col]++;
			if(is_ok(height[row][col])){
				printf("Yes\n");
				return;
			}
			height[row][col]--;
		}
	}
	printf("No\n");
}

int main(){

	while(true){
		scanf("%d %d %d %d",&H,&W,&CAP,&num_resident);
		if(H == 0 && W == 0 && CAP == 0 && num_resident == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3152
final_rank: 3

code_snippet: #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<deque>
#include<algorithm>
#include<numeric>
#include<utility>
#include<complex>
#include<functional>
 
using namespace std;

/* constant */

const int MAX_H = 20;
const int MAX_W = 20;
const int MAX_R = MAX_H * MAX_W;
const int INF = 1 << 30;

const int dxs[] = { 1, 0, -1, 0};
const int dys[] = { 0, -1, 0, 1};
  
/* typedef */

typedef vector<int> vi;
typedef pair<int,int> pii;

/* global variables */

int h, w, c, r;
int hgts[MAX_H][MAX_W];
pii ihpts[MAX_R];
bool ihbs[MAX_H][MAX_W], rgs[MAX_H][MAX_W], used[MAX_H][MAX_W];
int nrg;

/* subroutines */

void ngrgs(int y0, int x0) {
  if (! rgs[y0][x0]) return;
  queue<pii> q;
  q.push(pii(y0, x0));
  rgs[y0][x0] = false;
  nrg--;
  
  while (! q.empty()) {
    pii u = q.front(); q.pop();
    int& uy = u.first;
    int& ux = u.second;
    int uh = hgts[uy][ux];
    for (int di = 0; di < 4; di++) {
      int vy = uy + dys[di];
      int vx = ux + dxs[di];
      if (vy >= 0 && vy < h && vx >= 0 && vx < w &&
	  rgs[vy][vx] && hgts[vy][vx] >= uh) {
	rgs[vy][vx] = false;
	nrg--;
	q.push(pii(vy, vx));
      }
    }
  }
}

bool dam() {
  nrg = w * h;
  memset(rgs, true, sizeof(rgs));

  for (int y0 = 0; y0 < h; y0++) {
    ngrgs(y0, 0);
    ngrgs(y0, w - 1);
  }
  for (int x0 = 0; x0 < w; x0++) {
    ngrgs(0, x0);
    ngrgs(h - 1, x0);
  }

  for (int i = 0; i < r; i++)
    ngrgs(ihpts[i].first, ihpts[i].second);
  
  if (false) {
    for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) cout << rgs[y][x];
      cout << endl;
    }
  }

  while (nrg) {
    int y0 = 0, x0 = 0;
    while (! rgs[y0][x0]) 
      if (++x0 >= w) x0 = 0, y0++;

    int min_wl = INF, y1, x1;
    memset(used, false, sizeof(used));
    used[y0][x0] = true;
    queue<pii> q;
    q.push(pii(y0, x0));

    while (! q.empty()) {
      pii u = q.front(); q.pop();
      int& uy = u.first;
      int& ux = u.second;
      for (int di = 0; di < 4; di++) {
	int vy = uy + dys[di];
	int vx = ux + dxs[di];
	if (! rgs[vy][vx]) {
	  if (min_wl > hgts[vy][vx]) {
	    min_wl = hgts[vy][vx];
	    y1 = uy, x1 = ux;
	  }
	}
	else if (! used[vy][vx]) {
	  used[vy][vx] = true;
	  q.push(pii(vy, vx));
	}
      }
    }

    int wv = min_wl - hgts[y1][x1];
    memset(used, false, sizeof(used));
    used[y1][x1] = true;
    queue<pii> q0;
    q0.push(pii(y1, x1));

    while (! q0.empty()) {
      pii u = q0.front(); q0.pop();
      int& uy = u.first;
      int& ux = u.second;
      for (int di = 0; di < 4; di++) {
	int vy = uy + dys[di];
	int vx = ux + dxs[di];
	if (rgs[vy][vx] && ! used[vy][vx] && min_wl > hgts[vy][vx]) {
	  wv += min_wl - hgts[vy][vx];
	  used[vy][vx] = true;
	  q0.push(pii(vy, vx));
	}
      }
    }

    //printf("wv=%d\n", wv);
    if (wv >= c) return true;

    ngrgs(y1, x1);
  }

  return false;
}

/* main */

int main() {
  for (;;) {
    cin >> h >> w >> c >> r;
    if (h == 0) break;

    for (int y = 0; y < h; y++)
      for (int x = 0; x < w; x++) cin >> hgts[y][x];

    memset(ihbs, false, sizeof(ihbs));
    for (int i = 0; i < r; i++) {
      int y, x;
      cin >> y >> x;
      y--, x--;
      ihpts[i].first = y;
      ihpts[i].second = x;
      ihbs[y][x] = true;
    }

    bool ok = dam();

    for (int y = 0; ! ok && y < h; y++)
      for (int x = 0; ! ok && x < w; x++)
	if (! ihbs[y][x]) {
	  hgts[y][x]++;
	  ok = dam();
	  //printf("(%d,%d)=%d\n", y, x, ok);
	  hgts[y][x]--;
	}

    cout << (ok ? "Yes" : "No") << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 510
memory_kb: 1216
final_rank: 1

code_snippet: #include<cstdio>
#include<vector>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const int dx[]={1,0,-1,0},dy[]={0,-1,0,1};

int h,w,capa,a[20][20];
bool live[20][20];

bool check(int wall){ // 壁の高さの最小値
	bool vis[20][20]={};
	rep(i,h) rep(j,w) if(!vis[i][j] && a[i][j]<wall) {
		vis[i][j]=true;

		int sum=0;
		bool ok=true;
		int Q[20*20],head=0,tail=0;
		Q[tail++]=i*w+j;
		while(head<tail){
			int y=Q[head]/w,x=Q[head]%w; head++;

			if(live[y][x] || y==0 || y==h-1 || x==0 || x==w-1) ok=false;
			sum+=wall-a[y][x];

			rep(k,4){
				int yy=y+dy[k],xx=x+dx[k];
				if(0<=yy && yy<h && 0<=xx && xx<w && !vis[yy][xx] && a[yy][xx]<wall){
					vis[yy][xx]=true;
					Q[tail++]=yy*w+xx;
				}
			}
		}

		if(ok && sum>=capa) return true;
	}

	return false;
}

int main(){
	for(int m;scanf("%d%d%d%d",&h,&w,&capa,&m),h;){
		rep(i,h) rep(j,w) {
			scanf("%d",a[i]+j);
			live[i][j]=false;
		}
		rep(i,m){
			int y,x; scanf("%d%d",&y,&x); y--; x--;
			live[y][x]=true;
		}

		vector<int> as;
		rep(i,h) rep(j,w) {
			as.push_back(a[i][j]);
			as.push_back(a[i][j]+1);
		}
		sort(as.begin(),as.end());
		as.erase(unique(as.begin(),as.end()),as.end());

		rep(i,as.size()){
			if(check(as[i])) goto FOUND;
			rep(y,h) rep(x,w) if(!live[y][x]) {
				a[y][x]++;
				if(check(as[i])) goto FOUND;
				a[y][x]--;
			}
		}

		puts("No");
		continue;

		FOUND:
		puts("Yes");
	}

	return 0;
}
accuracy: 1
time_ms: 5290
memory_kb: 1048
final_rank: 2

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;

int dy[] = {0, 1, -1, 0};
int dx[] = {1, 0, 0, -1};

int h, w;
vector<vector<int> > height;
vector<vector<bool> > house;

int solve()
{
    int ret = 0;
    for(int y0=1; y0<=h; ++y0){
        for(int x0=1; x0<=w; ++x0){
            bool ng = false;
            int surround = INT_MAX;
            queue<pair<int, int> > q;
            q.push(make_pair(y0, x0));
            vector<vector<bool> > check(h+2, vector<bool>(w+2, false));
            check[y0][x0] = true;
            while(!q.empty()){
                int y = q.front().first;
                int x = q.front().second;
                q.pop();
                if(house[y][x]){
                    ng = true;
                    break;
                }

                for(int i=0; i<4; ++i){
                    int y2 = y + dy[i];
                    int x2 = x + dx[i];
                    if(height[y2][x2] <= height[y0][x0]){
                        if(!check[y2][x2]){
                            q.push(make_pair(y2, x2));
                            check[y2][x2] = true;
                        }
                    }else{
                        surround = min(surround, height[y2][x2]);
                    }
                }
            }

            if(ng)
                continue;

            int ret2 = 0;
            q.push(make_pair(y0, x0));
            check[y0][x0] = false;
            while(!q.empty()){
                int y = q.front().first;
                int x = q.front().second;
                q.pop();
                ret2 += surround - height[y][x];

                for(int i=0; i<4; ++i){
                    int y2 = y + dy[i];
                    int x2 = x + dx[i];
                    if(check[y2][x2]){
                        q.push(make_pair(y2, x2));
                        check[y2][x2] = false;
                    }
                }
            }
            ret = max(ret, ret2);
        }
    }

    return ret;
}

int main()
{
    for(;;){
        int c, r;
        cin >> h >> w >> c >> r;
        if(h == 0)
            return 0;

        height.assign(h+2, vector<int>(w+2, -1));
        for(int i=1; i<=h; ++i){
            for(int j=1; j<=w; ++j){
                cin >> height[i][j];
            }
        }

        house.assign(h+2, vector<bool>(w+2, false));
        for(int i=1; i<=h; ++i)
            house[i][0] = house[i][w+1] = true;
        for(int i=1; i<=w; ++i)
            house[0][i] = house[h+1][i] = true;
        for(int i=0; i<r; ++i){
            int y, x;
            cin >> y >> x;
            house[y][x] = true;
        }

        if(solve() >= c){
            cout << "Yes" << endl;
            continue;
        }

        bool ok = false;
        for(int i=1; i<=h; ++i){
            for(int j=1; j<=w; ++j){
                if(house[i][j])
                    continue;

                ++ height[i][j];
                if(solve() >= c){
                    ok = true;
                    break;
                }
                -- height[i][j];
            }
        }

        if(ok)
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
    }
}
accuracy: 1
time_ms: 6050
memory_kb: 1224
final_rank: 5

code_snippet: #include<iostream>
#include<algorithm>
#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()
#define pb         push_back
const int W = 20,H = 20;

int vol;
bool vis[H][W];
bool liv[H][W];
int    h[H][W];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};


void dfs(int r,int c,int y,int x,int water,bool &flag){
  if (x ==0 || y == 0 || x == c-1||y==r-1||liv[y][x]){
    flag=false;
  }
  if (vis[y][x])return ;
  vol+=water-h[y][x];
  vis[y][x]=true;
  
  rep(i,4){
    int nex=x+dx[i],ney=y+dy[i];
    if (nex == -1||ney==-1||nex==c||ney==r)continue;
    if (h[ney][nex] <water){
      dfs(r,c,ney,nex,water,flag);
    }
  }
  return;
}

bool compute(int r,int c,int C,int water){
  rep(i,r)rep(j,c)vis[i][j]=false;
  REP(i,1,r-1){
    REP(j,1,c-1){
      if (!vis[i][j] && h[i][j] < water){
	bool flag=true;
	vol=0;
	dfs(r,c,i,j,water,flag);
	if (flag&&vol >=C)return true;
      }
    }
  }
  return false;
}

bool check(int r,int c,int C){
  vector<int> val(r*c);
  rep(ii,r)rep(jj,c)val[ii*c+jj]=h[ii][jj];
  sort(ALL(val));
  val.erase(unique(ALL(val)),val.end());
  rep(ii,val.size())if (compute(r,c,C,val[ii]))return true;
  return false;
}

bool solve(int r,int c,int C){
  if (check(r,c,C))return true;
  rep(i,r){
    rep(j,c){
      if (liv[i][j])continue;
      h[i][j]++;
      if (check(r,c,C))return true;
      h[i][j]--;
    }
  }
  return false;
}

main(){
  int r,c,C,R;
  while(cin>>r>>c>>C>>R && r){
    rep(i,r){
      rep(j,c){
	cin>>h[i][j];
	liv[i][j]=false;
      }
    }
    rep(i,R){
      int y,x;
      cin>>y>>x;y--;x--;
      liv[y][x]=true;
    }
    if (solve(r,c,C))cout <<"Yes"<<endl;
    else cout << "No"<<endl;
  }
  return false;
}
accuracy: 1
time_ms: 6910
memory_kb: 916
final_rank: 4