标签:new ext point 描述 复杂 cin 容斥 一个 情况
一个棋盘有n条横线,m条竖线,上面有k个黑点,问有多少个不包含黑点的矩形。
数据范围:
n和m最大为1000,k最大为10
复杂度n*m*k
。
import java.awt.Point;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
public class Main {
int n, m;
long dp[][];
List<Point> black;
long solve() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int now = 0;//now表示以i,j这个点为右下角的矩形的个数
int lastX = 0;
int lastY = j;
for (int k = black.size() - 1; k >= -1; k--) {
//此处哨兵单元设计很巧妙,让k==-1的时候自动启用哨兵单元
Point p;
if (k == -1) p = new Point(i, 0);
else p = black.get(k);
if (p.y > j) continue;
if (p.x > i || p.x < lastX) continue;
now += (i - lastX) * (lastY - p.y);
lastX = p.x;
lastY = p.y;
}
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + now;
}
}
return dp[n][m];
}
Main() {
Scanner cin = new Scanner(System.in);
n = cin.nextInt();
m = cin.nextInt();
dp = new long[n + 1][m + 1];
black = new LinkedList<>();
int k = cin.nextInt();
while (k-- > 0) {
int r = cin.nextInt(), c = cin.nextInt();
black.add(new Point(r, c));
}
//对全部点进行排序(按照列从小到大进行排序)
black.sort(Comparator.comparing(x -> x.y));
for (int i = 0; i <= n; i++) dp[i][0] = 0;
for (int i = 0; i <= m; i++) dp[0][i] = 0;
long ans = solve();
System.out.println(ans);
}
public static void main(String[] args) {
new Main();
}
}
可以通过“缩点”法降低复杂度。
10个点有1024种情况,判断每种情况是否合理,然后统计个数即可。
复杂度之和k有关,跟n、m无关。
标签:new ext point 描述 复杂 cin 容斥 一个 情况
原文地址:https://www.cnblogs.com/weiyinfu/p/10164492.html