在我的任务中,我尝试使用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堆栈大小的情况下寻找答案。