[CSP] 201609-5 祭坛

本文详细解析了2016年9月CCF CSP认证的第五题——祭坛问题,探讨了如何通过水晶柱构建结界并找到最佳祭坛选址,涉及算法优化过程,包括朴素实现和逐步改进策略。
摘要由CSDN通过智能技术生成

如果世界上有祭坛的话,那么我估计会在上面,抱着我的小电脑瑟瑟发抖,恨不得析构自己,拿智商祭天
——题记

碎碎念

解题报告竟然搭配了题记,足以看出我内心的怨念。题目是CCF的CSP认证的2016年9月真题的第五题,我由于一些蜜汁原因在许久不刷OJ之后突然需要重拾旧手艺开始写程序。本来想的是,ACM课也刷了,题也写了,拿个400+总是应该的吧。结果做了真题,啪啪啪打脸。
题面比较长且是中文,本来不想赘述。然而考虑到CCF的破系统可能会直接崩掉,决定还是留一些资料来纪念。

题目

试题编号: 201609-5
试题名称: 祭坛
时间限制: 2.0s
内存限制: 256.0MB
问题描述: 问题描述
  在遥远的Dgeak大陆,生活着一种叫做Dar-dzo-nye的怪物。每当这种怪物降临,人们必须整夜对抗怪物而不能安睡。为了乞求这种怪物不再降临,人们决定建造祭坛。
  Dgeak大陆可以看成一个用平面直角坐标系表示的巨大平面。在这个平面上,有 n 个Swaryea水晶柱,每个水晶柱可以用一个点表示。
  如果 4 个水晶柱依次相连可以构成一个四边形,满足其两条对角线分别平行于 x 轴和 y 轴,并且对角线的交点位于四边形内部(不包括边界),那么这 4 个水晶柱就可以建立一个结界。其中,对角线的交点称作这个结界的中心。
  例如下左图中,水晶柱 ABCD 可以建立一个结界,其中心为 O。

  为了起到抵御Dar-dzo-nye的最佳效果,人们会把祭坛修建在最多层结界的保护中。其中不同层的结界必须有共同的中心,这些结界的边界不能有任何公共点,并且中心处也不能有水晶柱。这里共同中心的结界数量叫做结界的层数。
  为了达成这个目的,人们要先利用现有的水晶柱建立若干个结界,然后在某些结界的中心建立祭坛。
  例如上右图中,黑色的点表示水晶柱(注意 P 和 O 点不是水晶柱)。祭坛的一个最佳位置为 O 点,可以建立在 3 层结界中,其结界的具体方案见下左图。当然,建立祭坛的最佳位置不一定是唯一,在上右图中,O 点左侧 1 单位的点 P 也可以建立一个在 3 层结界中的祭坛,见下右图。

  现在人们想知道:
  1. 祭坛最佳选址地点所在的结界层数;
  2. 祭坛最佳的选址地点共有多少个。
输入格式
  输入的第一行包含两个正整数 n,q,表示水晶柱的个数和问题的种类。保证 q=1 或 2,其意义见输出格式。
  接下来 n 行,每行包含两个非负整数 x,y,表示每个水晶柱的坐标。保证相同的坐标不会重复出现。
输出格式
  若 q=1,输出一行一个整数,表示祭坛最多可以位于多少个结界的中心;若 q=2,输出一行一个整数,表示结界数最多的方案有多少种。
样例1输入
  26 1
  0 5
  1 1
  1 5
  1 9
  3 5
  3 10
  4 0
  4 1
  4 2
  4 4
  4 6
  4 9
  4 11
  5 0
  5 2
  5 4
  5 8
  5 9
  5 10
  5 11
  6 5
  7 5
  8 5
  9 10
  10 2
  10 5
样例1输出
  3
样例2输入
  26 2
  0 5
  1 1
  1 5
  1 9
  3 5
  3 10
  4 0
  4 1
  4 2
  4 4
  4 6
  4 9
  4 11
  5 0
  5 2
  5 4
  5 8
  5 9
  5 10
  5 11
  6 5
  7 5
  8 5
  9 10
  10 2
  10 5
样例2输出
  2
样例说明
  样例即为题目描述中的例子,两个样例数据相同,分别询问最多的结界数量和达到最多结界数量的方案数。
  其中图片的左下角为原点,右和上分别是 x 轴和 y 轴的正方向,一个格子的长度为单位长度。
  以图中的 O 点建立祭坛,祭坛最多可以位于 3 个结界的中心。不存在更多结界的方案,因此样例1的答案为 3。
  在 O 点左侧 1 单位的点 (4,5) 也可以建立一个在 3 个结界中的祭坛,因此样例2的答案为 2。
评测用例规模与约定
  对于所有的数据,保证存在至少一种方案,使得祭坛建造在至少一层结界中,即不存在无论如何祭坛都无法建造在结界中的情况。
  数据分为 8 类,各类之间互相没有交集,分别有以下特点:
  1. 占数据的 10%,n=200,x,y≤n;
  2. 占数据的 10%,n=200,x,y≤109;
  3. 占数据的 10%,n=1000,x,y≤n;
  4. 占数据的 10%,n=1000,x,y≤109;
  5. 占数据的 10%,n=5000,x,y≤n;
  6. 占数据的 10%,n=5000,x,y≤109;
  7. 占数据的 20%,n=300000,x,y≤n;
  8. 占数据的 20%,n=300000,x,y≤109。

  此外,每类数据中,q=1 与 q=2 各占恰好一半。

解题思路

Step 1

我的第一个想法是,什么鬼,这题妥妥超时上天啊。后面那些数据量那么大,估计会有什么逆天trick。然而科学实践告诉我们,做事需要先易后难,于是我初期的目标在于写一个不求时间但是能跑的代码。好吧事实上真实测评时,好像并不能够像ACM一样实时得到结果,所以估计我的分还要降…现在是先有了第一版朴素实现的代码,把有点的每一行建一个node,每一列建一个node,再去看可能的解。幸运的是,朴素算法过了30%的解。代码如下

//201609-5
// 30%
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class node
{
public:
    long long int id;
    vector<long long int> list;
    node(long long int inid = 0)
    {
        id = inid;
    }
    bool 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值