hihocoder234周 计算不包含黑点的矩形个数
问题描述
一个棋盘有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].st
ans %= 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
hihocoder234周 计算不包含黑点的矩形个数的更多相关文章
- 【Java】一个小程序,计算它包含的代码所需的耗时
写一个小程序,用来计算它包含的代码所需的耗时.虽然简单,测试代码是否耗时还是有点用的,不用重新写嘛~ import java.util.Date; import java.util.concurren ...
- 计算1到N中包含数字1的个数
转自:http://pandonix.iteye.com/blog/204840 Mark N为正整数,计算从1到N的所有整数中包含数字1的个数.比如,N=10,从1,2...10,包含有2个数字1. ...
- hdu2524 (求矩形个数,水题。。。)
hdu 2524 N - 暴力求解.打表 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64 ...
- Java实现 LeetCode 315 计算右侧小于当前元素的个数
315. 计算右侧小于当前元素的个数 给定一个整数数组 nums,按要求返回一个新数组 counts.数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i ...
- 计算阶乘n!末尾0的个数
一.问题描述 给定一个正整数n,请计算n的阶乘n!末尾所含有“0”的个数.例如: 5!=120,其末尾所含有的“0”的个数为1: 10!= 3628800,其末尾所含有的“0”的个数为2: 20!= ...
- 基于visual Studio2013解决面试题之0410计算二进制中1的个数
题目
- Java:判断字符串中包含某字符的个数
Java:判断字符串中包含某字符的个数 JAVA中查询一个词在内容中出现的次数: public int getCount(String str,String key){ if(str == null ...
- Leetcode 357.计算各个位数不同的数字个数
计算各个位数不同的数字个数 给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < 10n . 示例: 输入: 2 输出: 91 解释: 答案应为除去 11,22,33 ...
- Leetcode 315.计算右侧小于当前元素的个数
计算右侧小于当前元素的个数 给定一个整数数组 nums,按要求返回一个新数组 counts.数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元 ...
随机推荐
- CSS框架BluePrint
做惯了后台程序的我们,是否对前端编程有兴趣么,通过CSS框架,使我们很容易的开发出基于Div+CSS布局的页面来,今天让我们了解下大名鼎鼎的blueprint CSS框架吧! 它的官方网站:http: ...
- 配置Tomcat apr运行模式
tomcat中一共有三种运行模式,分别是:bio,nio,apr bio是阻塞式IO操作,使用的是传统的java i/o处理方式,对于每一个请求都要创建一个线程来进行处理,所以开销较大不适合处理高并发 ...
- 我对android davilk 虚拟机的理解
Davilk虚拟机作为Android平台的一部分.Google公司花了大量时间思考针对低功耗手持设备的优化设计.在智能手机出现之前,与桌面设备相比,手持设备在内存和速度方面落后8-10年.它们的计算能 ...
- StackPanel
StackPanel 的 HorizontalAlignment 属性和 VerticalAlignment 属性 默认情况下,这两个属性都被设置为 Stretch.
- angularJs中$controller的使用
$controller的使用 参考:https://stackoverflow.com/questions/27866620/can-someone-provide-a-use-case-for-th ...
- THINKPHP 验证码不显示
最近同事将我之前使用Thinkphp做的一个项目从香港服务器迁移到国内,但却遇到了图片验证码不显示的问题 但我确认了以下可能的问题后还是没有解决 PHP是否已经安装GD库支持: 输出之前是否有任何的输 ...
- ERROR: In <declare-styleable> MenuView, unable to find attribute android:preserveIconSpacing
eclipse sdk从低版本号切换到高版本号sdk的时候 v7包会包这个错ERROR: In <declare-styleable> MenuView, unable to fin ...
- android自己定义进度值可拖动的seekbar
近期忙找实习,加上实验室在推新项目,须要学习新知识.所以非常长一段时间没去整理了官博客了,github也蛮久没更新.非常羞愧.接下来还是要坚持写. 今天就简单的写一下我在项目中用到的算自己定义seek ...
- Android 获得图片并解码成缩略图以减少内存消耗
本文内容 环境 演示 下载 Demo 环境 Windows 2008 R2 64 位 Eclipse ADT V22.6.2,Android 4.4.3 SAMSUNG GT-I9008L,Andro ...
- Spring+hibernate+struts错题集
1.严重: Exception starting filter struts2 java.lang.ClassNotFoundException: org.apache.struts2.dispatc ...