05 2013 档案
摘要:题意:给出一张n*m的地图,'H'表示高地,不能部署炮兵,'P'表示平原,可以部署炮兵,炮兵之间必须保持横向、纵向至少2个格子的距离,保证没有误伤。问最多可以部署多少炮兵。分析:1.可以用一个32位整数存每一行的状态(二进制上1表示有布置炮兵,0表示没有布置炮兵),由于每一行的状态都要前两行的状态来决定,因此真正的一个状态应该包含本行的状态和上一行的状态,用dp[x][i][j]表示第x行上状态i,x-1行状态为j的最优解。2.每一行的状态其实只有60种,可以直接暴力搜索出来,把这60种状态按二进制递增顺序(排序目的是方便确定状态没有超出n*m的范围)存到数组s
阅读全文
摘要:题意:把价值为1,2,3,4,5,6的宝石平均分成两份,不能切割,有没有办法分开。分析:多重背包。之前直接用01背包的方法做78ms,然后想试试用二进制优化,看看能跑多少。发现,用二进制反而变421ms。#include <cstdio>int main(){ int marble[7],p = 1; bool knapsack[120000]; while(true) { int sum = 0; for(int i = 1;i <= 6;i++) { scanf("%d",&marble[i]); ...
阅读全文
摘要:题意:从N部电影中选M部看,每部都有不同的时长和价值,问是否可以看完M部电影,可以的话求价值的最大值,否则输出0.分析:这是有两重费用的01背包,其实原本就是在01背包的基础上加多一维就可以了。这题主要卡在"If DuoDuo can’t watch all of the movies that her uncle had bought for her, please output 0.",因此每个Knapsack[费用][费用]都是要刚刚好用到这么多,因此在输出的时候答案不一定是Knapsack[m][l],而是在Knapsack[m][?]里的其中一个。#include
阅读全文
摘要:题意:求一个点集中的两个点的最远距离的平方。分析:点集可以先用Graham-scan求凸包,再用Rotating Caliper求多边形外接圆直径。注意旋转卡壳中具体是先固定一条边,作为三角形的底边,再依次枚举除这两个点之外的其他点(逆时针顺序),用叉积求三角形的面积,面积最大时表明边与点的距离最远。#include <cstdio>#include <cmath>#include <algorithm>#define vector pointusing std::sort;using std::swap;using std::max;const doubl
阅读全文
摘要:题意:ACBoy有m天时间去学习n门课程,矩阵a中的元素a[i][j]表示用j天时间去学习课程i的收获。求最大收获。分析:背包题。01背包的基础上在最里面的循环加一个循环计算用各种天数学习第i门课程的收获即可。#include <cstdio>#include <algorithm>using std::max;int main(){ int n,m,knapsack[101],a[101][101]; while(scanf("%d%d",&n,&m) && (n || m)) { for(int i = 1;i &
阅读全文
摘要:题意:计算多边形核的面积。分析:半平面交的模板。有两个问题要注意,1.题目没说多边形点的顺序是顺时针还是逆时针,要先用面积的正负来判断点的顺序。2.题目中说坐标都在16位整数范围内,也就是说半平面交模板中初始的无限大平面的四个顶点设为±1e5就可以了,原本设为±1e15无限WA。#include <cstdio>#include <algorithm>#define vector pointusing std::swap;struct point{ double x,y; point(double xx = 0,double yy = 0) { x
阅读全文
摘要:题意:判断一个多边形内是否存在核。分析:半平面交的模板题。用半平面交来求多边形的核可以用在线算法还实现,这个算法把问题分解成凸多边形与半平面相交(这个半平面的分界线就是题目中的多边形的每一条边)。求凸多边形与半平面的交集的做法是,先定义一个空的多边形,枚举多边形的点,若点在半平面内就加到这里定义的多边形的点集里,若与多边形的边相交就计算交点,再把交点也放到点集里。#include <cstdio>#define vector pointstruct point{ double x,y; point(double xx = 0,double yy = 0) { x...
阅读全文
摘要:题意:计算一个多边形的面积。分析:题目中的答案要么是整数要么就是小数部分为0.5的小数,计算出中间结果之后判断能否被2整除,能就输出除以2得到的答案,不能就在这个答案后再加.5。总的面积要用64位int来保存。#include <cstdio>#include <cmath>#define vector pointstruct point{ int x,y; point(int xx = 0,int yy = 0) { x = xx; y = yy; } point operator - (const point& s) { ...
阅读全文
摘要:题意:在一个多边形宫殿外造围墙,要求与宫殿与围墙各处至少保持l英尺,求围墙最小长度。分析:凸包模板题,N次WA,百度空间里找到一组数据让程序出现runtime error,发现是Graham_scan里的while循环的结束条件缺少判断栈里的元素个数是否大于1。#include <cstdio>#include <cmath>#include <algorithm>#define vector pointusing std::sort;using std::swap;const double PI = acos(-1.00);struct point{ in
阅读全文
摘要:题意:给出一个超市一天24小时每个小时需要的人手,再给出n个应聘者的上班时间,每个人每次上班连续8个小时,问最少要聘请多少人。分析:c[i]表示第i小时需要的人手,t[i]表示第i小时开工的人数,s[i]表示最终聘请的人里面在[0,i]之间开始工作的人的总数。转化为不等式组:s[i+1]-s[i]>=0(i+1小时开始上班的人数最少是0),s[i+1]-s[i]<=t[i+1](i+1小时开始上班的人数最多为t[i+1]),j+8=i && s[i]-s[j]>=c[i],i=(j+8)%24 && s[i]-s[j]>=c[i]-mid
阅读全文
摘要:题意:给出两种关于防御站位置的信息,一种是确切的信息,P A B X,表示a在b北面x距离的地方,另一种是V A B,表示只知道A在B的北面。问这些信息有没有矛盾。分析:差分约束。第一种记为A-B>=X && A-B<=X,第二种记为A-B>=0,用SPFA求得解,则没有矛盾,否则就有矛盾。#include <iostream>#include <stdio.h>#include <queue>using namespace std;const int N=1001;const int E=2*100000+1000;con
阅读全文
摘要:题意:有一长度为10000000的墙,上面按时间顺序张贴长度不同,宽度相同,位置不一定相同的广告,问最终还能有多少广告能露出来。分析:线段树。每贴一张海报就是把一个连续的区间的值全部更改,但这里的数据比较大,直接做可能时间空间复杂度都很高。因为最多只有10000张海报,而即使每张海报的两个端点都不相同,最多就有20000个有用的端点,所以可以采用映射把这些位置离散化,把这些点由小到大映射到另一个数组里,然后的线段树的操作就可以只在这个数组里进行了。#include<cstdio>#include<algorithm>using std::sort;struct line
阅读全文
摘要:题意:一个矩形箱子,左上角与右下角的坐标给出,里面有n块板把箱子里的空间分隔成许多个分区,给出这些板在上边的x坐标、下边的x坐标,以及一堆玩具的坐标,求这些分区里的玩具数目。分析:记玩具在点p0,某块板的上边点是p1,下边点是p2,p2p1(向量)×p2p0>0表示p0在p1p2的左面,<0表示在右面。接下来就是用二分法找出每个点所在的分区。叉积+二分查找#include<cstdio>#define vector pointstruct point{ int x,y; point(int xx,int yy) { x = xx; y = yy; ...
阅读全文
摘要:题意:一个正方形密室边长是10,内部有平行y轴方向的n堵墙,每堵墙都有两道门。要从(0,5)走到(10,5)最短距离是多少?分析:每道门的两个端点以及起点终点作为节点,要求起点到终点的最短路,建图时结合线段相交来判断两个顶点之间是否可达,就枚举这两个顶点之间的墙与这两个顶点相连而成的线段有没有相交,相交则不可达,不相交则为这线段的长度。Dijkstra + 线段相交判断,数据的组织要清晰。#include<cstdio>#include<cmath>#define vector pointstruct point{ double x,y; point(double xx
阅读全文

浙公网安备 33010602011771号