当前位置: 首页 > news >正文

P2460[SDOI2007] 科比的比赛

第一次做洛谷系列,紧张,请多关照哦

题目传送门:[SDOI2007] 科比的比赛 - 洛谷

 

思路分析

这道题大概题意是给定我们的主人公 Kobe Bryant 的 mm 个对手,nn 场比赛相对应的获胜概率。求 Kobe Bryant 最大全部获胜概率和打败对手能力值之和。

这道题可以使用 dfs 的思路解决。但是 Kobe Bryant 的对手非常多(也就是 mm 的值非常大),直接搜索的时间复杂度肯定非常高,就需要一些有效的剪枝。

最容易想到的是最优性剪枝,也就是如果当目前答案已经不优于已经存在的答案就可以直接放弃这个答案。

具体来说就是在 dfs 函数中加入:

if(cmp_double(tmp1,ans1)==0) return;

但是这样的优化显然是明显不够的。

这个题目有一个写的很明显特性是 n≤mn≤m。由于 nn 的值很小,而 Kobe Bryant 在每场比赛只能对战一个对手,所以 Kobe Bryant 只需要对战 nn 个对手并不是 mm 个。翻译成白话文就是 Kobe Bryant 可以只找弱的打,也就是找成功概率高的打。根据这个特性,我们可以在搜索时只搜前 nn 弱的对手。也可以理解这个剪枝是贪心的思路,因此 Kobe Bryant 的对手就少了很多。再根据前一条剪枝可以拿到 4040 分。

最后考虑到的是可以使用启发式搜索剪枝优化,对当前的结果进行估计,也就是即使是当前状态的最优情况,目前 Kobe Bryant 的获胜概率仍然没有已有最优情况高的时候舍弃。为了保证估计的效率,可以使用预处理的方式让每次询问复杂度降到 O(n)O(n)。

进行以上三次优化的思路是已经可以通过本题了。

代码

#include<bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define antirep(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e6,M=1e3;
const double err=1e-10;
bool vst[N];
double ans1,pr[N],Gl[N];
int n,m,a[N],ans2;
struct node{int id;double p;}k[M][M];
int cmp_double(double x,double y){if(abs(x-y)<err) return 2;if(x-y>err) return 1;if(x-y<err) return 0;return 0x7fffffff;
}
bool cmp(node x,node y){if(cmp_double(x.p,y.p)==2) return a[x.id]>a[y.id];return x.p>y.p;
}
int f(int cur,double tmp1){return cmp_double(tmp1*pr[cur],ans1);
}
void prepare(){pr[n]=k[n][1].p;antirep(i,n-1,1)pr[i]=pr[i+1]*k[i][1].p;
}
void dfs(int cur,double tmp1,int tmp2){if(cur>n){if(cmp_double(tmp1,ans1)==1||cmp_double(tmp1,ans1)==2){ans1=tmp1;if(tmp2>ans2) ans2=tmp2;}return;}if(cmp_double(tmp1,ans1)==0) return;if(f(cur,tmp1)==0)return;rep(i,1,n){int ID=k[cur][i].id;if(vst[ID]==1) continue;vst[ID]=1;tmp1*=k[cur][i].p,tmp2+=a[ID];dfs(cur+1,tmp1,tmp2);tmp1/=k[cur][i].p,tmp2-=a[ID],vst[ID]=0;}return;
}
signed main(){cin>>n>>m;rep(i,1,m) cin>>a[i];rep(i,1,n){rep(j,1,m)cin>>k[i][j].p,k[i][j].id=j;sort(k[i]+1,k[i]+1+m,cmp);}prepare();dfs(1,1,0);cout<<fixed<<setprecision(12)<<ans1<<endl;cout<<ans2<<endl;return 0;
}

这里对代码进行一些解释,因为本题是浮点数操作,浮点数会在精度很高的时候产生误差,因此这里使用了 cmp_double 函数进行比较浮点数大小。

预处理之所以是逆序的储存是因为正序的搜索每次询问的都是剩余比赛的最有情况。

排序可以保证把 Kobe Bryant 最弱(也就是获胜概率最高)的对手放在每场比赛的最前面。

后记

备注:Kobe Bryant 是本题主人公科比的原名。而在 20202020 年,科比本人乘坐的西科斯基 S−76S−76 直升机在美国加利福尼亚州洛杉矶县卡拉巴萨斯市坠毁。年仅 4141 岁。

虽然我们不能跟题目重所描述的那样帮助科比赢得比赛,但是我们可以通过解出这道题淡化对科比离去的哀伤。

牢大,我想你了。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • PyTorch--深度学习
  • 开源通用验证码识别OCR —— DdddOcr 源码赏析(一)
  • [C#]winform基于opencvsharp结合Diffusion-Low-Light算法实现低光图像增强黑暗图片变亮变清晰
  • 基于改进YOLOv8的景区行人检测算法
  • C语言——函数专题
  • LSTM 模型原理
  • Python----爬虫
  • django之select_related 与 prefetch_related用法
  • windows C++- C++/WinRT和COM组件(下)
  • Python编写Word文档
  • css-定位
  • 【Linux】——进程概念(万字解读)
  • 【嵌入式linux开发】智能家居入门6:最新ONENET,物联网开放平台(QT、微信小程序、MQTT协议、ONENET云平台、旭日x3派)
  • Linux环境下运行介绍
  • 51单片机学习
  • 【刷算法】求1+2+3+...+n
  • Android交互
  • exif信息对照
  • express + mock 让前后台并行开发
  • github从入门到放弃(1)
  • Java方法详解
  • Netty源码解析1-Buffer
  • Python socket服务器端、客户端传送信息
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 动态魔术使用DBMS_SQL
  • 问题之ssh中Host key verification failed的解决
  • 我这样减少了26.5M Java内存!
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • gunicorn工作原理
  • 阿里云重庆大学大数据训练营落地分享
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • ​LeetCode解法汇总518. 零钱兑换 II
  • ###C语言程序设计-----C语言学习(3)#
  • #define
  • (4)STL算法之比较
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • (C++17) optional的使用
  • (k8s中)docker netty OOM问题记录
  • (创新)基于VMD-CNN-BiLSTM的电力负荷预测—代码+数据
  • (二)pulsar安装在独立的docker中,python测试
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)Google的Objective-C编码规范
  • (转)菜鸟学数据库(三)——存储过程
  • .ai域名是什么后缀?
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .net 7和core版 SignalR
  • .NET Framework 服务实现监控可观测性最佳实践
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .net开发引用程序集提示没有强名称的解决办法
  • .NET开源纪元:穿越封闭的迷雾,拥抱开放的星辰
  • .net流程开发平台的一些难点(1)