java.lang.StackOverflowError用于二分图中最大匹配的重合函数(Kuhn算法)

时间:2013-12-06 17:58:53

标签: java algorithm recursion stack-overflow matching

在我的任务中,我尝试使用Kuhn算法找到二分图中最大匹配的解。

  

问题描述:

     

地板在一个大小为M×N的房间铺有镶木地板。但是,有些   瓷砖地板坏了。彼得决定重新装修房间   更换受损细胞。他发现镶木地砖进来了   两种类型 - 1×2的大小,这需要一个硬币(一点点思考,   彼得意识到1×2瓷砖可以旋转90度,从而   生产瓷砖2×1)和尺寸1×1,这是B币。彼得不能   将双层瓷砖分成两部分。

     

找出修理地板的最低费用。

     

规格:输入:第一行包含四个数字:N,M,   A,B(1≤N,M≤300,A,B - 模数不超过1000)。   接下来的N行中的每一行都包含M个字符:“。” (点)代表   未破坏的瓷砖地板,符号“*”(星号) - 损坏。在   行的结尾可以是无关紧要的空格。在结束时   文件可能是空字符串。

     

输出:一个数字 - 要修理的最低金额。

对于第一个输入行300 300 1000 1000和接下来300个等于300行星号的行,当递归调用1024次时,我得到Exception in thread "main" java.lang.StackOverflowError at java.util.ArrayList.iterator

我的代码如下:

import java.io.*;
import java.util.*;

public class BrokenParquet {
    static boolean findPath(List<Integer>[] g, int u1, int[] matching, boolean[] vis) {
        if (vis[u1]) return false;
        vis[u1] = true;
        for (int v : g[u1]) {
            int u2 = matching[v];
            if (u2 == -1 || !vis[u2] && findPath(g, u2, matching, vis)) {
                matching[v] = u1;
                return true;
            }
        }
        return false;
    }

    public static int maxMatching(List<Integer>[] g, int n2) {
        int n1 = g.length;
        int[] matching = new int[n2];
        Arrays.fill(matching, -1);
        int matches = 0;
        for (int u = 0; u < n1; u++) {
            if (findPath(g, u, matching, new boolean[n1]))
                ++matches;
            /*if (matches>36300)
                System.out.println(matches);*/
        }
        return matches;
    }

    public static void main(String[] args) throws Exception {

        BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in));
        int n=0,m=0,a=0,b=0;

            String s = "";

        try {
            int c;

                StringBuilder sb = new StringBuilder();

                while ((c = rdr.read()) != '\n') {
                    sb.append((char) c);
                    s = sb.toString();
                    s.trim();
                }
        } catch (IOException e) {
            System.exit(0);
            e.printStackTrace();
        }

        if (s == null) System.exit(0);
            String[] num = s.split("[^\\p{Digit}*]");

        if (num.length != 4) System.exit(0);

        try {
             n = Integer.parseInt(num[0]);
             m = Integer.parseInt(num[1]);
             a = Integer.parseInt(num[2]);
             b = Integer.parseInt(num[3]);
        } catch(Exception e) {System.exit(0);}
        if (n<1 || m<1 || n>300 || m>300 || a>1000 || b>1000 || a<0 || b<0) System.exit(0);
        char[][] chars = new char[n][m];
        s = "";


                try {

                        int c;
                    for (int i = 0; i < chars.length; i++) {
                        StringBuilder sb = new StringBuilder();
                        int l = 0;
                        while ((c = rdr.read()) != -1) {
                        if ((char) c == '\n') break;
                        if (((char) c == '*' || (char) c == '.') && l<m) {
                            sb.append((char) c);
                            l++;
                        }
                    }
                        if (l < m) for (int j = 0; j < m-l; j++) sb.append('.');
                        s = sb.toString();



                        chars[i] = s.toCharArray();
                    }
                    rdr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (rdr != null) {
                        try {
                            rdr.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }

            rdr.close();
        int n1 = m*n;
        int n2 = n1;
        List<Integer>[] g = new List[n1];
        for (int i = 0; i < n1; i++) {
            g[i] = new ArrayList<Integer>();
        }
        int o = 0, w = 0;
        for (int i = 0; i < chars.length; i++) {
            for (int j = 0; j < chars[i].length; j++) {
                char c = chars[i][j];
                if (c == '*') {
                    w++;
                    if (j > 0 && chars[i][j-1] == '*') g[o].add(o-1);
                    if (j <= chars[i].length-2 && chars[i][j+1] == '*') g[o].add(o+1);
                    if (i > 0 && chars[i-1][j] == '*') g[o].add(o-m);
                    if (i <= chars.length-2 && chars[i+1][j] == '*') g[o].add(o+m);
                }
                o++;
            }
        }
        int d = maxMatching(g, n2)/2;
        if (2*b>a) System.out.print(d*a+(w-d*2)*b);
        else System.out.print(w * b);

        }
    }
你能帮帮我吗?我在不增加Java堆栈大小的情况下寻找答案。

0 个答案:

没有答案