题目链接

问题描述

一个棋盘有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无关。

相似问题

codeforce上有一道规模更大的题,n和m为10000,k为20:
http://codeforces.com/gym/101350/problem/G

51nod
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1291

#include<bits/stdc++.h>
using namespace std;
#define st first
#define nd second
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define sz(x) (int)x.size()
#define de(x) cout<< #x<<" = "<<x<<endl
#define dd(x) cout<< #x<<" = "<<x<<" "
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;const int N = 666;
int n, m, top;
int u[N], sta[N];
ll c[N][N];
char s[N];int main() {scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) {scanf("%s", s+1);for(int j = 1; j <= m; j++)u[j] = (s[j] == '1')? u[j]+1: 0;top = 0;sta[top++]=0;for(int j = 1; j <= m+1; j++) {while(u[sta[top-1]] > u[j]) {++c[max(u[sta[top-2]], u[j])+1][j-sta[top-2]-1];//维护单调上升的栈, 看每个柱块向左和向右的最大延伸距离, 即为宽度--c[u[sta[top-1]]+1][j-sta[top-2]-1];            //枚举i为底边, 对高度范围为[max(u[sta[top-2]],u[j])+1, u[sta[top-1]]], 宽度为j-sta[top-2]-1的矩形加1--top;}while(top && u[sta[top-1]] == u[j]) --top;sta[top++] = j;}}for(int i = 2; i <= n; i++) for(int j = 1; j <= m; j++) c[i][j] += c[i-1][j]; //c1[i, j]: 高为i (n^2) 的连通块, 只统计最长宽度的。for(int i = 1; i <= n; i++) {for(int j = m-1; j; j--) c[i][j] += c[i][j+1];    //c2[i, j]: 高i宽 >= j的连通块的个数for(int j = m-1; j; j--) c[i][j] += c[i][j+1];  //c3[i, j]: 高i宽j的全1矩阵的个数}for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) printf("%lld%c", c[i][j], " \n"[j == m]);return 0;
}
/*
3 3
011
110
110
如何得到c1? 暴力的话, c1是枚举n^2的上下边界, 优化后, 变成枚举直方图的最底边,快速统计各个不同的上顶边。这个可以通过单调栈+差分解决。求前缀和后就得到c1。
总的时间复杂度为O(nm).
c1
0 3 0
1 1 0
1 0 0
c2
3 3 0
2 1 0
1 0 0
c3
6 3 0
3 1 0
1 0 0*/

leetcode
https://www.nowcoder.com/acm/contest/79/D

#include<bits/stdc++.h>
using namespace std;
#define st first
#define nd second
typedef long long ll;
const int mod = 1e9+7;
pair<int, int> s[5111];
int main() {int n, m, c;scanf("%d%d%d", &n, &m, &c);for(int i = 1, x, y; i <= c; i++) scanf("%d%d", &x, &y), s[i] = {x, y};sort(s+1, s+c+1);long long ans = 0;for(int i = 1; i <= c; i++){int l = 0, r = m+1;for(int j = i-1; ~j; j--){                                                            //从下往上从左往右枚举之前的点ans += (r-s[i].nd)*(n-s[i].st+1LL)%mod*(s[j+1].st-s[j].st)%mod*(s[i].nd-l)%mod;    //上边界为s[j].st ~ s[j+1].stans %= mod;if(s[j].nd > s[i].nd) r = min(r, s[j].nd);if(s[j].nd < s[i].nd) l = max(l, s[j].nd);}} //n*m矩阵的子矩阵个数 = 左右两边界 * 上下两边界 long long cnt = (n*(n+1LL)/2%mod)*(m*(m+1LL)/2%mod)%mod;ans = (cnt-ans)%mod;if(ans < 0) ans += mod;printf("%lld\n", ans);return 0;
}

参考资料

https://www.cnblogs.com/dirge/p/10034268.html

转载于:https://www.cnblogs.com/weiyinfu/p/10164492.html

hihocoder234周 计算不包含黑点的矩形个数相关推荐

  1. Learning Log:输入一个天数,计算天数包含多少周和剩余的天数

    做了一个小题目:输入一个天数,计算天数包含多少周和剩余的天数. 运用好取整和取余运算 运算符 / :除法运算符,并且运算结果遵从向下取整. 运算符 % :模运算.(取余数) (1).当运算符左边小于右 ...

  2. 编程之美计算0到N中包含数字1的个数

    转自:http://blog.csdn.net/hongjuntu123/article/details/8743266 有这样一个函数f(n),对于任意正整数n,它表示从 0 到 n 之间出现&qu ...

  3. Java面试题:给定一个整数,按10进制来看,计算里面包含多少个0

    代码如下: package com.moson.interview;/*** 给定一个整数,按10进制来看,计算里面包含多少个0* @author moxingjian* @version 1.0* ...

  4. python计算能够包含两个圆的最小圆

    给定两个圆的圆心和半径,计算能够包含两个圆的最小圆 # Defines two classes, Point() and Disk(). # The latter has an "area& ...

  5. hive中如何进行按周计算

    最近遇到一个需求,有一些统计数据,原本是按月更新的计算的,但是现在要按周更新计算. 在hive表中,月更数据一般按照一个月的最后一天进行分区存储,那么如果是按月更新的话直接根据分区进行计算就可以了. ...

  6. python3--日期时间处理最近n个自然周计算

    第一部分:最近n个自然周计算 算法逻辑: 1.12日是星期三,近一自然周是从1.10开始的日期,中间相差2天 1.13日是星期四,近一自然周是从1.10开始的日期,中间相差3天 1.14日是星期五,近 ...

  7. 合天网安 在线实验 CTF竞赛 writeup(第六周 | 套娃一样的上传、第二十一周 | 你的空格哪去了、第十周 | 试试协议吧、第十一周 | 签到般的包含、第九周 | 试下phpinfo吧)

    文章目录 第六周 | 套娃一样的上传 第二十一周 | 你的空格哪去了 第十周 | 试试协议吧 第十一周 | 签到般的包含 第九周 | 试下phpinfo吧 第六周 | 套娃一样的上传 图片上传题目,看 ...

  8. JAVA 计算日期属于当月第几周(日期周计算)

    计算日期属于当月第几周(日期周计算) 本文周计算时间方式为:当月第一个周一为第一周 计算 获取月第一个周一.从当月第一天开始找 第一个周一时间与 sourceTime [传入时间对比],sourceT ...

  9. 第2关:计算二叉树的深度和节点个数

    #include <iostream> #include "binary_tree.h"BiTreeNode* CreatBiTree(char* s, int &am ...

最新文章

  1. 如何有效抵抗电脑辐射
  2. 策略路由和路由策略的不同
  3. LeetCode题组:第836题-矩形叠加
  4. VMware迁移到OpenStack私有云要了解的那些事
  5. Android之SwipeRefreshLayout嵌套RecyclerView遇到的坑
  6. mysql 读写分离
  7. java f.lenth返回值_long length
  8. Redis(二)原理以及主从复制的实现
  9. c3p0使用 与批量生成
  10. 苹果移动设备用什么管理比较好?有什么推荐?
  11. linux work 账户管理,Homework Week-3 用户管理
  12. 食品行业仓储条码管理系统解决方案
  13. 微信发送模板消息返回data format error hint 47001
  14. 智齿客服Android集成流程,智齿客服接入_智齿客服客服系统如何接入网站_智齿客服接入流程_企业服务汇...
  15. 4种文件扩展名被阻止时发送邮件附件的方法
  16. 大数据文字游戏_什么是大数据?
  17. 极路由php插件,极路由SDK
  18. Web 和http协议
  19. 《自学大全》—营造学习氛围
  20. APS系统如何让企业实现“多赢”?看高博通信是怎么做的

热门文章

  1. zookeeper使用分布式锁
  2. spring5源码-ioc容器
  3. 关于Windows 2019 antimalware 进程占用CPU 过多的处理方法 关闭windows 病毒防护的方法...
  4. spring boot(三)Junit 测试controller
  5. 数据结构-堆 C与C++的实现
  6. 向窗口发送ctrl c复制 消息
  7. 利用jquery 控制select 实例代码
  8. 《设计模式详解》行为型模式 - 命令模式
  9. 页面显示拒绝访问请求
  10. 中低频量化交易策略研发03_注意事项与应对