hihocoder234周 計算不包含黑點的矩形個數
阿新 • • 發佈:2018-12-23
問題描述
一個棋盤有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無關。