2424. 保龄球

题目链接

2424. 保龄球

JYY 很喜欢打保龄球,虽然技术不高,但是还是总想着的高分。

这里 JYY 将向你介绍他所参加的特殊保龄球比赛的规则,然后请你帮他得到尽量多的分数。

一场保龄球比赛一共有 N 个轮次,每一轮都会有 10 个木瓶放置在木板道的另一端。

每一轮中,选手都有两次投球的机会来尝试击倒全部的 10 个木瓶。

对于每一次投球机会,选手投球的得分等于这一次投球所击倒的木瓶数量。

选手每一轮的得分是他两次机会击倒全部木瓶的数量。

对于每一个轮次,有如下三种情况:

  1. “全中”:如果选手第一次尝试就击倒了全部 10 个木瓶,那么这一轮就称为“全中”。在一个“全中”轮中,由于所有木瓶在第一次尝试中都已经被击倒,所以选手不需要再进行第二次投球尝试。同时,在计算总分时,选手在下一轮的得分将会被乘 2 计入总分。

  2. “补中”:如果选手使用两次尝试击倒了 10 个木瓶,那么这一轮就称为“补中”。同时,在计算总分时,选手在下一轮中的第一次尝试的得分将会被乘以 2 计入总分。

  3. “失误”:如果选手未能通过两次尝试击倒全部的木瓶,那么这一轮就被称为“失误”。同时,在计算总分时,选手在下一轮的得分会被计入总分,没有分数被翻倍。

此外,如果第 N 轮是“全中”,那么选手可以进行一次附加轮:也就是,如果第 N 轮是“全中”,那么选手将一共进行 N+1 轮比赛。

显然,在这种情况下,第 N+1 轮的分数一定会被加倍。

附加轮的规则只执行一次。

也就是说,即使第 N+1 轮选手又打出了“全中”,也不会进行第 N+2 轮比赛。

因而,附加轮的成绩不会使得其他轮的分数翻番。

最后,选手的总得分就是附加轮规则执行过,并且分数按上述规则加倍后的每一轮分数之和。

JYY 刚刚进行了一场 N 个轮次的保龄球比赛,但是,JYY 非常不满意他的得分。

JYY 想出了一个办法:他可以把记分表上,他所打出的所有轮次的顺序重新排列,这样重新排列之后,由于翻倍规则的存在,JYY 就可以得到更高的分数了!

当然了,JYY 不希望做的太假,他希望保证重新排列之后,所需要进行的轮数和重排前所进行的轮数是一致的:

比如如果重排前 JYY 在第 N 轮打出了“全中”,那么重排之后,第 N 轮还得是“全中”以保证比赛一共进行 N+1 轮;同样的,如果 JYY 第 N 轮没有打出“全中”,那么重排过后第 N 轮也不能是全中。

请你帮助 JYY 计算一下,他可以得到的最高的分数。

输入格式

第一行包含一个整数 N,表示保龄球比赛所需要进行的轮数。

接下来包含 N 或者 N+1 行,第 i 行包含两个非负整数 XiYi,表示 JYY 在这一轮两次投球尝试所得到的分数,Xi 表示第一次尝试,Yi 表示第二次尝试。

我们用 10 0 表示一个“全中”轮。

输入数据保证合法,当且仅当 Xn=10,Yn=0 时,存在 N+1XiYi

输出格式

输出一行一个整数,表示 JYY 最大可能得到的分数。

数据范围

1leNle50

输入样例:

2 5 2 10 0 3 7

输出样例:

44

样例解释

按照输入顺序,JYY 将得到 37 分。

最佳方案是将 3 个轮次排列成如下顺序:

3 7 10 0 5 2

解题思路

模拟退火

模拟退火可以用来解决连续函数的全局最优值问题,本题显然随机交换两个点变化不大,即是一个连续函数,故可用模拟退火来解决本问题

  • 时间复杂度:O()

代码

// Problem: 保龄球 // Contest: AcWing // URL: https://www.acwing.com/problem/content/description/2426/ // Memory Limit: 64 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=55; PII a[N]; int n,m,res; int cal() { int ret=0; for(int i=0;i<m;i++) { ret+=a[i].fi+a[i].se; if(i<n) { if(a[i].fi==10)ret+=a[i+1].fi+a[i+1].se; else if(a[i].fi+a[i].se==10)ret+=a[i+1].fi; } } res=max(res,ret); return ret; } void simulate_anneal() { for(double t=1e4;t>1e-4;t*=0.99) { int x=rand()%m,y=rand()%m; int xx=cal(); swap(a[x],a[y]); if(n+(a[n-1].fi==10)==m) { int yy=cal(); if(exp((yy-xx)/t)<(double)rand()/RAND_MAX)swap(a[x],a[y]); } else swap(a[x],a[y]); } } int main() { cin>>n; m=n; for(int i=0;i<n;i++)cin>>a[i].fi>>a[i].se; if(a[n-1].fi==10) { cin>>a[n].fi>>a[n].se; m++; } while((double)clock()/CLOCKS_PER_SEC<0.8)simulate_anneal(); cout<<res<<'\n'; return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16731504.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(126)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示