AOJ 2287 Water Clock
G : 水時計
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2287
問題概要
同じ大きさの立方体の箱が座標に配置されていて、
一部は繋がっていたりする。
どこかから水を流す。
それぞれおかれている高さは異なっていて、
水があふれると、隣り合う箱が高さが高いものがあった場合はそちらには溢れない。
箱がないor自分より低い位置に箱があるときは流れる。
溢れる量/流れることができる場所の量の水が流れる。
時間と場所が指定されるので、
その場所の水槽の水の高さを求めよ。
解法
シミュレーション
まず、箱の関係をグラフにする。
時間ごとに流すのではなく、
流すべき箱にすべての水を流してしまってから、そこから
配るという実装をした。(ループがないので。
ソース
#include<iostream> #include<vector> #define REP(i,b,n) for(int i=b;i<(int)n;i++) #define rep(i,n) REP(i,0,n) #define FOR(it,o) for(__typeof((o).begin()) it=(o).begin(); it!=(o).end(); ++it) using namespace std; const int N = 10; const int dx[] = {0, 1, 0, -1}, dy[] = {-1, 0, 1, 0}; int height[N][N], color[N][N]; int H, W, numC; double sourceFlow; pair<int, int> beginPos; vector<pair<int, int> > toFlow[N*N]; double capa[N*N], volume[N*N], area[N*N]; const double C = 30.0 * 30 * 30; const double A = 30.0 * 30.0; void init(){ rep(i, N)rep(j, N)color[i][j] = -1; numC = 0; rep(i, N*N){ toFlow[i].clear(); capa[i] = 0; volume[i] = 0; area[i] = 0; } } void reset(){ rep(i, N*N)volume[i] = 0; } bool input(){ cin >> W >> H; if(W + H == 0)return false; init(); cin >> beginPos.second >> beginPos.first >> sourceFlow; rep(i, H){ rep(j, W){ cin >> height[i][j]; } } return true; } bool validPos(int y, int x){ if(y < 0 || x < 0 || y >= H || x >= W)return false; return true; } void putColor(int y, int x, int c){ if(height == 0)return; color[y][x] = c; capa[c]+= C; area[c] += A; rep(i, 4){ int nx = dx[i] + x, ny = dy[i] + y; pair<int, int> nextPos(ny, nx); if(!validPos(ny, nx)){ toFlow[c].push_back(nextPos); continue; } if(height[ny][nx] > height[y][x])continue; if(height[ny][nx] < height[y][x]){ toFlow[c].push_back(nextPos); continue; } if(color[ny][nx] != -1)continue; putColor(ny, nx, c); } } void beginColor(){ rep(i, H){ rep(j, W){ if(color[i][j] != -1 || height[i][j] == 0)continue; putColor(i, j, numC); numC++; } } } void Flow(int y, int x, double v){ int myColor = color[y][x]; if(myColor == -1)return; volume[myColor] += v; if(volume[myColor] < capa[myColor])return; double remain = volume[myColor] - capa[myColor]; volume[myColor] = capa[myColor]; FOR(it, toFlow[myColor]){ if(!validPos(it->first, it->second))continue; Flow(it->first, it->second, remain / (double)toFlow[myColor].size()); } } double getHeight(int y, int x){ int myColor = color[y][x]; return volume[myColor] / area[myColor]; } int main(){ while(input()){ beginColor(); int n; cin >> n; rep(i, n){ int time, y, x; cin >> time >> x >> y; reset(); Flow(beginPos.first, beginPos.second, sourceFlow * (double)time); cout <<(int)getHeight(y, x) << endl; } } return 0; }