2014校招 Google在线测试第二场题解 C

C.  Hex
题意简要是:两人玩游戏,判断当前状态。有四种状态:不可能的出现的状态、红赢、蓝赢、还没人赢。棋盘的格子是六边形,看原题有图。红、蓝轮流下子,红下红子,蓝下篮子,随机先手。红色如果把从上到下连通了,则赢。蓝色如果把从左到右连通了,则赢。一旦有人赢棋局就结束了。

判断连通性,可以转化成图来思考。通过遍历就能知道。分别看一下四种状态如何判断。
1、不可能出现的状态:
     1)红色、蓝色棋子数量差大于1
     2)某一方赢了,但是棋子还少一个
     3)双方都赢了.
     4)某一方赢了,但是去掉最后下的棋子,还是赢的状态
2、红赢、或者蓝赢
     在可能出现的状态中,如果上下通过红子连通,则红赢。如果左右通过篮子连通,则蓝赢
3、还没人赢
     不是以上三种情况,则没人赢。

通过计数,和遍历比较好的判断了所有情况,只有一种例外:1种的4)去掉最后下的棋子,还是赢的状态。
接下来分析如何判断这种情况。

直观的,枚举每一个棋子,去掉一个棋子后,看是否还是赢的状态,如果不是了,就认为这是最后下的棋子。如果没有找到这个棋子,说明就是不可能出现的状态。 枚举的办法应该是可以通过small数据集,但是large就显得太慢了。

是否存在删除某个点后,这两点(这两点指的是上边和下边,把边看成一个节点,不是棋子)就不连通的,就是说这两点之间的简单路径是不是唯一。想到了最大流,如果路径唯一,最大流则是1。最大流是在边上面的容量,这里是点上的容量,所以需要对图做一点改动,把除原点和终点外,的中间节点都拆分成两个,左节点和右节点,然后通过大小为1的边连接,原图中的入边都进左节点,出边都从右节点。这样就好了。代码如下:
[java]  view plain copy
  1. import java.io.BufferedReader;  
  2. import java.io.BufferedWriter;  
  3. import java.io.FileNotFoundException;  
  4. import java.io.FileReader;  
  5. import java.io.FileWriter;  
  6. import java.io.IOException;  
  7. import java.io.OutputStreamWriter;  
  8. import java.math.BigInteger;  
  9. import java.util.ArrayList;  
  10. import java.util.Arrays;  
  11. import java.util.Collections;  
  12. import java.util.LinkedList;  
  13. import java.util.List;  
  14. import java.util.Queue;  
  15.   
  16. public class HelloWorld {  
  17.      
  18.     static int n;  
  19.     static int[] preOrder;  
  20.     static int[] backOrder;  
  21.     static int[][] graph;  
  22.     static int[] len;  
  23.     static int seq;  
  24.     static int root;  
  25.     static int[] dx = {00, -1, -111};  
  26.     static int[] dy = {-1101, -10};  
  27.   
  28.     static class MaxFlow {  
  29.         class Edge {  
  30.             int to;  
  31.             int cap;  
  32.             int rev;  
  33.              
  34.             Edge(int to, int cap, int rev) {  
  35.                 this.to = to;  
  36.                 this.cap = cap;  
  37.                 this.rev = rev;  
  38.             }  
  39.         }  
  40.          
  41.         int V;  
  42.         Edge[][] G;  
  43.         int[] len;  
  44.         int[] level;  
  45.         int[] iter;  
  46.         int INF = Integer.MAX_VALUE;  
  47.          
  48.         MaxFlow(int n) {  
  49.             V = n;  
  50.             G = new Edge[n][16];  
  51.             len = new int[n];  
  52.             Arrays.fill(len, 0);  
  53.             level = new int[n];  
  54.             iter = new int[n];  
  55.         }  
  56.          
  57.         void addEdge(int from, int to, int cap) {  
  58.             expand(from);  
  59.             expand(to);  
  60.             G[from][len[from]++] = new Edge(to, cap, len[to]);  
  61.             G[to][len[to]++] = new Edge(from, 0, len[from] - 1);  
  62.         }  
  63.          
  64.         void expand(int index) {  
  65.             if (G[index].length == len[index]) {  
  66.                 Edge[] tmp = new Edge[len[index] * 2];  
  67.                 for (int i = 0; i < len[index]; i++)  
  68.                     tmp[i] = G[index][i];  
  69.                 G[index] = tmp;  
  70.             }  
  71.         }  
  72.          
  73.         void bfs(int s) {  
  74.             Arrays.fill(level, -1);  
  75.             Queue<Integer> que = new LinkedList<Integer>();  
  76.             level[s] = 0;  
  77.             que.add(s);  
  78.             while (!que.isEmpty()) {  
  79.                 int v = que.poll();  
  80.                 for (int i = 0; i < len[v]; i++) {  
  81.                     Edge e = G[v][i];  
  82.                     if (e.cap > 0 && level[e.to] < 0) {  
  83.                         level[e.to] = level[v] + 1;  
  84.                         que.add(e.to);  
  85.                     }  
  86.                 }  
  87.             }  
  88.         }  
  89.          
  90.         int dfs(int v, int t, int f) {  
  91.             if (v == t) return f;  
  92.             for (int i = iter[v]; i < len[v]; i++, iter[v]++) {  
  93.                 Edge e = G[v][i];  
  94.                 if (e.cap > 0 && level[v] < level[e.to]) {  
  95.                     int d = dfs(e.to, t, Math.min(f, e.cap));  
  96.                     if (d > 0) {  
  97.                         e.cap -= d;  
  98.                         G[e.to][e.rev].cap += d;  
  99.                         return d;  
  100.                     }  
  101.                 }  
  102.             }  
  103.             return 0;  
  104.         }  
  105.          
  106.         int maxFlow(int s, int t) {  
  107.             int flow = 0;  
  108.             for (;;) {  
  109.                 bfs(s);  
  110.                 if (level[t] < 0return flow;  
  111.                 Arrays.fill(iter, 0);  
  112.                 int f;  
  113.                 while ((f = dfs(s, t, INF)) > 0) {  
  114.                     flow += f;  
  115.                 }  
  116.             }  
  117.         }  
  118.     }  
  119.      
  120.     public static void main(String[] args) {  
  121.         try {  
  122. //            BufferedReader br = new BufferedReader(new FileReader("D:/codejam/a.txt"));  
  123. //            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));  
  124.              
  125. //            BufferedReader br = new BufferedReader(new FileReader("D:/codejam/C-small-practice.in"));  
  126. //            BufferedWriter bw = new BufferedWriter(new FileWriter("D:/codejam/C-small-result.txt"));  
  127. //            BufferedReader br = new BufferedReader(new FileReader("D:/codejam/A-small-attempt1.in"));  
  128.              
  129.             BufferedReader br = new BufferedReader(new FileReader("D:/codejam/C-large-practice.in"));  
  130.             BufferedWriter bw = new BufferedWriter(new FileWriter("D:/codejam/C-large-result.txt"));  
  131.   
  132.             String line;  
  133.              
  134.             line = br.readLine();  
  135.             int T = Integer.parseInt(line);  
  136.              
  137.             for (int cas = 1; cas <= T; cas++) {  
  138.                 line = br.readLine();  
  139.                 n = Integer.parseInt(line);  
  140.                 String[] table = new String[n];  
  141.                 int numR = 0;  
  142.                 int numB = 0;  
  143.                 for (int i = 0; i < n ;i++) {  
  144.                     table[i] = br.readLine();  
  145.                     for (int j =0 ;j < n;j++) {  
  146.                         numR += (table[i].charAt(j) == 'R') ? 1 : 0;  
  147.                         numB += (table[i].charAt(j) == 'B') ? 1 : 0;  
  148.                     }  
  149.                 }  
  150.                  
  151.                 String ans = "";  
  152.                 if (Math.abs(numR - numB) > 1) {  
  153.                     ans = "Impossible";  
  154.                 } else {  
  155.                     boolean winR = false;  
  156.                     boolean winB = false;  
  157.                     int src = n * n * 2;  
  158.                     int dest = n * n * 2 + 1;  
  159.                      
  160.                     MaxFlow flow = new MaxFlow(n * n * 2 + 2);  
  161.                     // dfs R  
  162.                     for (int i = 0; i < n ;i++)  
  163.                         for (int j = 0;j < n; j++) if (table[i].charAt(j) == 'R') {  
  164.                             int node = i * n + j;  
  165.                             flow.addEdge(node, node + n*n, 1);  
  166.                             for (int k = 0; k< 6; k++) {  
  167.                                 int ni = i + dx[k];  
  168.                                 int nj = j + dy[k];  
  169.                                 if (inTable(ni, nj) && table[ni].charAt(nj) == 'R') {  
  170.                                     flow.addEdge(node + n * n, ni * n + nj, 1);  
  171.                                 }  
  172.                             }  
  173.                         }  
  174.                     for (int i = 0; i < n; i++) {  
  175.                         if (table[0].charAt(i) == 'R') {  
  176.                             flow.addEdge(src, i, 1);  
  177.                         }  
  178.                         if (table[n-1].charAt(i) == 'R') {  
  179.                             flow.addEdge((n-1) * n + i + n * n, dest, 1);  
  180.                         }  
  181.                     }  
  182.                      
  183.                     int ret = flow.maxFlow(src, dest);  
  184.                     if (ret > 1) ans = "Impossible";  
  185.                     if (ret == 1) {  
  186.                         winR = true;  
  187.                         if (numR < numB) ans = "Impossible";  
  188.                     }  
  189.                      
  190.                     //  dfs B;  
  191.                     flow = new MaxFlow(n * n * 2 + 2);  
  192.                     for (int i = 0; i < n ;i++)  
  193.                         for (int j = 0;j < n; j++) if (table[i].charAt(j) == 'B') {  
  194.                             int node = i * n + j;  
  195.                             flow.addEdge(node, node + n*n, 1);  
  196.                             for (int k = 0; k< 6; k++) {  
  197.                                 int ni = i + dx[k];  
  198.                                 int nj = j + dy[k];  
  199.                                 if (inTable(ni, nj) && table[ni].charAt(nj) == 'B') {  
  200.                                     flow.addEdge(node + n * n, ni * n + nj, 1);  
  201.                                 }  
  202.                             }  
  203.                         }  
  204.                     for (int i = 0; i < n; i++) {  
  205.                         if (table[i].charAt(0) == 'B') {  
  206.                             flow.addEdge(src, i * n, 1);  
  207.                         }  
  208.                         if (table[i].charAt(n-1) == 'B') {  
  209.                             flow.addEdge(i * n + n - 1 + n * n, dest, 1);  
  210.                         }  
  211.                     }  
  212.                      
  213.                     ret = flow.maxFlow(src, dest);  
  214.                     if (ret > 1) ans = "Impossible";  
  215.                     if (ret == 1) {  
  216.                         winB = true;  
  217.                         if (numB < numR) ans = "Impossible";  
  218.                     }  
  219.                      
  220.                      
  221.                     if (ans.length() == 0) {  
  222.                         if (!winR && !winB) {  
  223.                             ans = "Nobody wins";  
  224.                         } else if (winR && winB) {  
  225.                             ans = "Impossible";  
  226.                         } else if (winR) {  
  227.                             ans = "Red wins";  
  228.                         } else {  
  229.                             ans = "Blue wins";  
  230.                         }  
  231.                     }  
  232.                 }  
  233.                  
  234.                  
  235.                 bw.write("Case #" + cas + ": " + ans);  
  236.                 bw.newLine();  
  237.                 bw.flush();  
  238.             }  
  239.              
  240.             br.close();  
  241.             bw.close();  
  242.         } catch (FileNotFoundException e) {  
  243.             e.printStackTrace();  
  244.         } catch (IOException e) {  
  245.             e.printStackTrace();  
  246.         }  
  247.     }  
  248.   
  249.     private static boolean inTable(int x, int y) {  
  250.         return x >= 0 && x < n && y >= 0 && y < n;  
  251.     }  
  252.   
  253. }  
  254. http://blog.csdn.net/albani/article/details/12685667
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值