AOJ2287 Water Clock
問題リンク Water Clock
- 解法
水槽クラスを使って実装しました。
水を流しいれる箇所は1か所なので、その場所へfq*tの水を一気に流します。溢れた水を隣接するマスへ流す処理を再帰処理して解きます。いかにミス無く実装できるかがカギとなります。
類題にAOJ1133があります。個人的には今回の問題の方が実装しやすかったです。
- ソース
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; //Water Clock public class AOJ2287 { class Tank{ List<int[]> pos; double height; int id, edge; public Tank(int id) { this.id = id; height = 0; pos = new ArrayList<int[]>(); } void add(int pi, int pj){ pos.add(new int[]{pi, pj}); edge = 0; for(int[] a:pos){ for(int k=0;k<4;k++){ int ni = a[0]+move[k][0]; int nj = a[1]+move[k][1]; if(0<=ni&&ni<h&&0<=nj&&nj<w){ if(map[ni][nj]<map[a[0]][a[1]])edge++; } else edge++; } } } void f(double V){ double vh = V/30/30/pos.size(); double dh = 30-height; double mh = Math.min(vh, dh); height+=mh; vh-=mh; if(vh<EPS)return; double giveV = vh*30*30*pos.size()/edge; if(giveV<EPS)return; for(int[]a:pos)for(int k=0;k<4;k++){ int ni = a[0]+move[k][0]; int nj = a[1]+move[k][1]; if(0<=ni&&ni<h&&0<=nj&&nj<w&&map[ni][nj]<map[a[0]][a[1]]&&tanks[ni][nj]!=0){ ref.get(tanks[ni][nj]).f(giveV); } } } } int[][] move = {{-1,0},{0,1},{1,0},{0,-1}}; int w, h, fi, fj, q; int[][] map, tanks; Map<Integer, Tank> ref; boolean[][] u; double EPS = 1e-8; void union(int i, int j, int id, int H){ for(int k=0;k<4;k++){ int ni = i+move[k][0]; int nj = j+move[k][1]; if(0<=ni&&ni<h&&0<=nj&&nj<w&&!u[ni][nj]&&map[ni][nj]==H){ Tank t = ref.get(id); t.add(ni, nj); ref.put(id, t); u[ni][nj] = true; tanks[ni][nj] = id; union(ni, nj, id, H); } } } void flow(int t){ double fq = t*q; ref.get(tanks[fi][fj]).f(fq); } void run(){ Scanner sc = new Scanner(System.in); for(;;){ w = sc.nextInt(); h = sc.nextInt(); if((w|h)==0)break; fj = sc.nextInt(); fi = sc.nextInt(); q = sc.nextInt(); map = new int[h][w]; for(int i=0;i<h;i++)for(int j=0;j<w;j++)map[i][j] = sc.nextInt(); ref = new HashMap<Integer, Tank>(); tanks = new int[h][w]; u = new boolean[h][w]; int id = 1; for(int i=0;i<h;i++)for(int j=0;j<w;j++){ if(map[i][j]==0||u[i][j])continue; Tank t = new Tank(id); t.add(i, j); tanks[i][j] = id; ref.put(id, t); u[i][j] = true; union(i, j, id, map[i][j]); id++; } int L = sc.nextInt(); while(L--!=0){ int time = sc.nextInt(); int pj = sc.nextInt(), pi = sc.nextInt(); for(int i:ref.keySet())ref.get(i).height = 0; flow(time); System.out.println((int)ref.get(tanks[pi][pj]).height); } } } public static void main(String[] args) { new AOJ2287().run(); } }