P2831 [NOIP 2016 提高组] 愤怒的小鸟 题解

news/2025/10/6 11:12:27/文章来源:https://www.cnblogs.com/petercode-314/p/19127363

传送门

洛谷

题目大意

每关给你最多18只小猪(后文皆为18只),问你最少用几条过原点抛物线全部干掉。
注意这里 \(m\) 其实没用,因为你要是会算最优解了为啥还需要部分分啊?

思路

\(n\leq18\) ,不是暴搜就是状压。直接放弃暴搜。
状压dp做法:

1. 处理抛物线

首先记录这18只小猪所有可能产生的抛物线,如图所示为例1的第一组样例
image
注意这里“所有”可能产生的抛物线,包括只经过一只小猪(* ̄(oo) ̄) 的抛物线。
这个时候就有人会问,为了记录抛物线,需要记录 \(y=ax^2+bx\) 中的 \(a,b\) ,那要是记录只经过一只小猪的抛物线,还得考虑不经过其他小猪,岂不是要算废。
其实解决方法很简单,我们对于每条抛物线不记录两个存在误差的浮点 \(a,b\) 而是直接用二进制下的18位整数状压这条抛物线经过的小猪,可以证明对每只小猪一定存在只过它一点的抛物线。
记录只有一个点的抛物线很重要,我第一遍没有搞,结果过了样例,导致因为这个问题调了好久,有时还纳闷这个dp有没有真的考虑所有情况。

然后就是考虑过多个小猪的抛物线。先枚举第一只小猪,然后枚举下标在第一只小猪之后的小猪。计算出过这两只猪的抛物线,然后看其他小猪是否在此抛物线上,记录在对应的抛物线数组里即可。
代码实现:

#include <bits/stdc++.h>
using namespace std;
typedef pair<double, double> pdd;
const int N = 18, ZT = 1 << N;
const double eps = 1e-6; // 处理浮点数相等的精度问题, 凡差小于epsilon即算相等
int n, m;
double x[N], y[N];
int para[2000], cnt; // records parabolas// 计算过两点的抛物线
pdd calc(double x1, double y1, double x2, double y2)
{pdd res;double &a = res.first, &b = res.second;a = (x1 * y2 - x2 * y1) / (x1 * x2 * (x2 - x1));b = (x2 * x2 * y1 - x1 * x1 * y2) / (x1 * x2 * (x2 - x1));// printf("The parabola that goes through (%lf, %lf) and (%lf, %lf) is:\n\ty=%lfx^2+%lfx\n", x1, y1, x2, y2, a, b);return res;
}
void solve()
{// pre-calculate the parabolasfor (int i = 0; i < n; ++i) {para[cnt++] = (1 << i); // 只打小猪i的抛物线int vst = 0;for (int j = i + 1; j < n; ++j) {if (vst & (1 << j)) continue;// if (x[i] == x[j]) continue; // 防止calc函数出现除以0,但是好像不加也没影响照样ACpdd tmp = calc(x[i], y[i], x[j], y[j]);if (tmp.first >= 0) continue; // 题面要求抛物线开口向下,这不是数学,是物理!para[cnt] = (1 << i);for (int k = j; k < n; ++k) { // 这里k从j开始枚举,或者直接para[cnt]|=(1<<j),然后这里j+1开始枚举也没问题// printf("trying the parabola on (%lf, %lf): ", x[k], y[k]);double res = tmp.first * x[k] * x[k] + tmp.second * x[k];// printf("result is %lf\n", res);if (abs(res - y[k]) <= eps) {// printf("Success! It IS on the parabola!\n");vst |= (1 << k); // 防止再次枚举到过小猪 i,j,k的抛物线para[cnt] |= (1 << k);}}++cnt;}}// for (int i = 0; i < cnt; ++i) {// 	printf("parabola %d goes through these pigs: ", i);// 	for (int j = 0; j < n; ++j) {// 		if (para[i] & (1 << j)) {// 			printf("%d ", j);// 		}// 	}// 	printf("\n");// }
}

注意抛物线数组开大点,不要以为抛物线最多只有18条,我们记录的是每一条可能的抛物线。

2. dp

显然对于每个状态 \(i(0\leq i\leq 2^{n+1}-1)\) ,枚举每条抛物线 \(para_j\) 带来的影响,有:

\[\text{dp}[i|\text{para}_j]=\min(\text{dp}[i|\text{para}_j],\,\text{dp}[i]+1) \]

至此,已成艺术完结撒花。

代码(含调试+原版注释)

#include <bits/stdc++.h>
using namespace std;
typedef pair<double, double> pdd;
const int N = 18, ZT = 1 << N;
const double eps = 1e-6;
int n, m;
double x[N], y[N];
int para[2000], cnt; // records parabolas
int dp[ZT];
pdd calc(double x1, double y1, double x2, double y2)
{pdd res;double &a = res.first, &b = res.second;a = (x1 * y2 - x2 * y1) / (x1 * x2 * (x2 - x1));b = (x2 * x2 * y1 - x1 * x1 * y2) / (x1 * x2 * (x2 - x1));// printf("The parabola that goes through (%lf, %lf) and (%lf, %lf) is:\n\ty=%lfx^2+%lfx\n", x1, y1, x2, y2, a, b);return res;
}
void solve()
{cnt = 0;cin >> n >> m;for (int i = 0; i < n; ++i) {cin >> x[i] >> y[i];}// pre-calculate the parabolasfor (int i = 0; i < n; ++i) {para[cnt++] = (1 << i); // 只打小猪i的抛物线int vst = 0;for (int j = i + 1; j < n; ++j) {if (vst & (1 << j)) continue;// if (x[i] == x[j]) continue;// printf("pig %d and pig %d: ", i, j);pdd tmp = calc(x[i], y[i], x[j], y[j]);if (tmp.first >= 0) continue;para[cnt] = (1 << i);for (int k = j; k < n; ++k) {// printf("trying the parabola on (%lf, %lf): ", x[k], y[k]);double res = tmp.first * x[k] * x[k] + tmp.second * x[k];// printf("result is %lf\n", res);if (abs(res - y[k]) <= eps) {// printf("Success! It IS on the parabola!\n");vst |= (1 << k);para[cnt] |= (1 << k);}}++cnt;}}// for (int i = 0; i < cnt; ++i) {// 	printf("parabola %d goes through these pigs: ", i);// 	for (int j = 0; j < n; ++j) {// 		if (para[i] & (1 << j)) {// 			printf("%d ", j);// 		}// 	}// 	printf("\n");// }const int FULL = (1 << n) - 1;for (int i = 1; i <= FULL; ++i) dp[i] = 30;for (int i = 0; i <= FULL; ++i) {for (int j = 0; j < cnt; ++j) {dp[i | para[j]] = min(dp[i | para[j]], dp[i] + 1);}}cout << dp[FULL] << '\n';
}
int main()
{// freopen("F.in", "r", stdin);// freopen("F.out", "w", stdout);ios::sync_with_stdio(false);cin.tie(nullptr);int T;cin >> T;for (int i = 1; i <= T; ++i) {// printf("########### TEST CASE %d ###########\n", i);solve();// printf("\n");}return 0;
}

代码(无//)

#include <bits/stdc++.h>
using namespace std;
typedef pair<double, double> pdd;
const int N = 18, ZT = 1 << N;
const double eps = 1e-6;
int n, m;
double x[N], y[N];
int para[2000], cnt;
int dp[ZT];
pdd calc(double x1, double y1, double x2, double y2)
{pdd res;double &a = res.first, &b = res.second;a = (x1 * y2 - x2 * y1) / (x1 * x2 * (x2 - x1));b = (x2 * x2 * y1 - x1 * x1 * y2) / (x1 * x2 * (x2 - x1));return res;
}
void solve()
{cnt = 0;cin >> n >> m;for (int i = 0; i < n; ++i) {cin >> x[i] >> y[i];}for (int i = 0; i < n; ++i) {para[cnt++] = (1 << i);int vst = 0;for (int j = i + 1; j < n; ++j) {if (vst & (1 << j)) continue;pdd tmp = calc(x[i], y[i], x[j], y[j]);if (tmp.first >= 0) continue;para[cnt] = (1 << i);for (int k = j; k < n; ++k) {double res = tmp.first * x[k] * x[k] + tmp.second * x[k];if (abs(res - y[k]) <= eps) {vst |= (1 << k);para[cnt] |= (1 << k);}}++cnt;}}const int FULL = (1 << n) - 1;for (int i = 1; i <= FULL; ++i) dp[i] = 30;for (int i = 0; i <= FULL; ++i) {for (int j = 0; j < cnt; ++j) {dp[i | para[j]] = min(dp[i | para[j]], dp[i] + 1);}}cout << dp[FULL] << '\n';
}
int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);int T;cin >> T;for (int i = 1; i <= T; ++i) solve();return 0;
}

别跑,还有压行版

#include<bits/stdc++.h>
using namespace std;typedef pair<double,double>pdd;const int N=18,ZT=1<<N;const double eps=1e-6;int n,m;double x[N],y[N];int para[2000],cnt;int dp[ZT];pdd calc(double x1,double y1,double x2,double y2){pdd res;double&a=res.first,&b=res.second;a=(x1*y2-x2*y1)/(x1*x2*(x2-x1));b=(x2*x2*y1-x1*x1*y2)/(x1*x2*(x2-x1));return res;}void solve(){cnt=0;cin>>n>>m;for(int i=0;i<n;++i){cin>>x[i]>>y[i];}for(int i=0;i<n;++i){para[cnt++]=(1<<i);int vst=0;for(int j=i+1;j<n;++j){if(vst&(1<<j))continue;pdd tmp=calc(x[i],y[i],x[j],y[j]);if(tmp.first>=0)continue;para[cnt]=(1<<i);for(int k=j;k<n;++k){double res=tmp.first*x[k]*x[k]+tmp.second*x[k];if(abs(res-y[k])<=eps){vst|=(1<<k);para[cnt]|=(1<<k);}}++cnt;}}const int FULL=(1<<n)-1;for(int i=1;i<=FULL;++i)dp[i]=30;for(int i=0;i<=FULL;++i){for(int j=0;j<cnt;++j){dp[i|para[j]]=min(dp[i|para[j]],dp[i]+1);}}cout<<dp[FULL]<<'\n';}int main(){ios::sync_with_stdio(false);cin.tie(nullptr);int T;cin>>T;for(int i=1;i<=T;++i)solve();return 0;}

总结

挺容易写的一道蓝题,没调太久。
算是自己想不出,一听到枚举抛物线就懂的题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/929252.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

t型布局网站怎么做移动网站开发公司

无限网络应用越来越广泛&#xff0c;由此应运而生了许多可以蹭网的软件&#xff0c;家里的网速突然变慢了&#xff0c;也许就是隔壁的小哥哥小姐姐在蹭网络&#xff0c;那么如何避免被蹭网&#xff1f;今天小编给各位小伙伴推荐几款路由器管理软件&#xff0c;发现网络变慢了&a…

网站建设功能要求做男女之间的事情的网站

1.1 APT攻击简介 1.1.1APT攻击概念 网络安全&#xff0c;尤其是Internet互联网安全正在面临前所未有的挑战&#xff0c;这主要就来自于有组织、有特定目标、持续时间极长的新型攻击和威胁&#xff0c;国际上有的称之为APT&#xff08;Advanced Persistent Threat&#xff09;攻…

网站开发公司商业计划书国家备案网查询系统

1 socket本地通信 socket原本是为网络通讯设计的&#xff0c;但后来在socket框架的基础上发展出了一种IPC&#xff08;进程通信&#xff09;机制&#xff0c;即UNIX Domain Socket&#xff0c;专门用来实现使用socket实现的本地进程通信。 本地通信的流程与使用的接口与基于TC…

企顺网网站建设做网站费用上海

文章目录 78. 子集&#xff08;集合的所有子集&#xff09;90. 子集 II&#xff08;集合的所有子集&#xff09;792. 匹配子序列的单词数&#xff08;判断是否为子集&#xff09;500. 键盘行&#xff08;集合的交集&#xff09;409. 最长回文串&#xff08;set&#xff09; 更多…

库存中心(三层库存模型)

目录背景和价值WMS一、货主(Owner)货主(Owner)业务对象的核心属性:3. 库存记录:细化到「SKU+货主+库位」三维度逻辑库存一、逻辑层核心业务对象设计1. 库存主档(LogicalInventory):核心载体参考资料 背景和价…

Valley靶机渗透实战:从凭证复用到Python库劫持

本文详细记录了TryHackMe平台Valley靶机的完整渗透过程,涵盖端口扫描、目录枚举、FTP凭证破解、PCAP分析、SSH登录、UPX脱壳和Python库劫持提权等技术要点。Valley靶机渗透报告 - TryHackMe 本文详细记录了我渗透TryH…

深入解析:IP Search Performance Tests dat/db/xdb/mmdb 结构性能差异对比

深入解析:IP Search Performance Tests dat/db/xdb/mmdb 结构性能差异对比pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-famil…

联盟文明网站建设有新突破建设学校网站需要具备

文章目录 指令和参数筛选器远程指令tasklist参数 windows批处理系列&#xff1a;初步&#x1fa9f;命令行设置 指令和参数 tasklist可以获取当前运行的程序列表。当不加参数时&#xff0c;其返回值包括5列&#xff0c;分别是映像名称&#xff0c;PID&#xff0c;会话名&#…

重庆好的网站制作公司济南seo网站排名优化工具

文 | Flood Sung源 | 知乎前言今年最热门的词汇之一当属内卷了。似乎很多行业都由于份额有限而陷入内卷当中。最火的或许是清华学生的这张图&#xff0c;“骑车写代码”&#xff1a;图片来自网络虽然后来知道是这位同学怕关了屏幕程序就断了&#xff0c;但这不禁让人思考&#…

C++篇:002

C++篇:002$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");C++篇:002.模板 一、模板概念 函数模板 函数模板的格式: template<typename T1, typename T…

10.05模拟赛反思

打得太差了。 T1 由于限制了 \(60\) 步导致挂掉 \(50 pts\)。写代码的时候不能太想当然了,只是期望每次减半而不是严格的。有时候写代码觉得是对的就写了,但是可能到了很后面才发现有问题,更严重的话根本不知道有问…

MariaDB收购SkySQL增强AI与无服务器能力

开源数据库公司MariaDB重新收购其前子公司SkySQL,整合其具备AI能力的无服务器云数据库平台。此次收购将增强MariaDB Cloud的代理AI功能和向量数据库支持,提升多云部署灵活性。MariaDB收购前子公司SkySQL以增强代理AI…

单片机寄存器的四种主要类型! - 实践

单片机寄存器的四种主要类型! - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Mona…

手把手教做网站wordpress媒体库全选

Redis 发展到现在已经有 9 种数据类型了&#xff0c;其中最基础、最常用的数据类型有 5 种&#xff0c;它们分别是&#xff1a;字符串类型、列表类型、哈希表类型、集合类型、有序集合类型&#xff0c;而在这 5 种数据类型中最常用的是字符串类型&#xff0c;所以本文我们先从字…

ASP.NET Core API 自定义全局异常

ASP.NET Core API 自定义全局异常using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters;namespace LG.ERP.API.CustomerFilters {/// <summary>/// 自定义异常过滤器/// </summary>pu…

TDengine 高级特性——读缓存

TDengine 高级特性——读缓存pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco"…

织梦做信息类网站电子商务营销方向

codeforces 453C Little Pony and Summer Sun Celebration 这道题很有意思&#xff0c;虽然网上题解很多了&#xff0c;但是我还是想存档一下我的理解。 题意可以这样转换&#xff1a;初始所有点有 \(01\) 状态&#xff0c;每经过一次状态就翻转&#xff0c;求一条路径使得最后…

非合作博弈之软性均衡:东方智慧与西方理论的融合框架

非合作博弈之软性均衡:东方智慧与西方理论的融合框架 一、引言:冲突与均衡的再思考 在传统博弈理论中,非合作博弈的均衡往往被视为一种静态的、稳定的状态,在这种状态下,任何参与者都没有单方面改变策略的动机。然…

如何快速搭建spring-boot工程 - murphy

导入maven依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>3.5.4</version> </dependency>在…

详细介绍:相机--双目立体相机

详细介绍:相机--双目立体相机2025-10-06 10:48 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !importan…