当前位置: 首页 > 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 岁。

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

牢大,我想你了。

http://www.lryc.cn/news/426784.html

相关文章:

  • linux学习--第二天
  • 使用 Flask、Celery 和 Python 实现每月定时任务
  • 【c语言】整数在内存中的储存(大小端字节序)
  • 浅谈SIMD、向量化处理及其在StarRocks中的应用
  • 【ML】Image Augmentation)的作用、使用方法及其分类
  • 设计模式六大原则(一)--单一职责原则
  • c语言学习,malloc()函数分析
  • 【运维项目经历|041】上云项目-物理机迁移到阿里云
  • 分组并合并其它列的非空值 --Excel难题#83
  • VM相关配置及docker
  • Redis中Set数据类型常用命令
  • mysql误删数据恢复记录
  • 论文阅读:Real-time Controllable Denoising for Image and Video
  • 【Kubernetes】虚拟 IP 与 Service 的代理模式
  • 深度学习·Pytorch
  • fastzdp_sqlmodel新增get_first和is_exitsts方法
  • 嵌入式软件--数电基础 DAY 3
  • 【生成式人工智能-十五-经典的影像生成方法-GAN】
  • python 已知x+y=8 求x*y*(x-y)的最大值
  • windows平台的postgresql主从数据库流备份
  • Spring 常见设计模式
  • 优化大量数据导出到Excel的内存消耗(二):如果数据超出Excel单表上限,则进行分表
  • rustrover打开会报Error: Invalid toolchain
  • docker-compose 安装canal
  • Unity动画模块 之 3D Rig页签
  • 【蓝桥杯冲刺省一,省一看这些就够了-Java版本】蓝桥杯日期问题相关模板以及练习题
  • 【经典算法】BFS_FloodFill算法
  • RocketMQ之Topic主题详解
  • 实战OpenCV之图像显示
  • I2C的10-bit地址空间