国王游戏.2333_微扰(邻项交换)证明

国王邀请大臣玩游戏,根据大臣左右手的数字确定奖赏金币数。目标是重新排列队伍,使最多奖赏尽可能少。贪心策略是按大臣左手数字升序排列,通过微扰法证明其正确性。最后一位大臣获得的金币为1*2*7/6=2。证明最优解是将大臣按左手数字从小到大排序。

  • 题目描述

恰逢 H 国国庆,国王邀请 t 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 t 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:「排在该大臣前面的所有人的左手上的数的乘积」除以「他自己右手上的数」,然后向下取整得到的结果。

国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。

输入

第一行包含一个整数 t,表示大臣的人数。

第二行包含两个整数 n 和 m,n,m之间用一个空格隔开,分别表示国王左手和右手上的整数。

接下来t 行,每行包含两个整数 x 和 y,x,y之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。

输出

输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

样例输入

3
1 1
2 3
7 4
4 6

样例输出

2

提示

  • 按 1、2、3 号大臣这样排列队伍,获得奖赏最多的大臣所获得金币数为2 ;

  • 按 1、3、2 这样排列队伍,获得奖赏最多的大臣所获得金币数为2 ;

  • 按 2、1、3 这样排列队伍,获得奖赏最多的大臣所获得金币数为2;

  • 按 2、3、1 这样排列队伍,获得奖赏最多的大臣所获得金币数为 9;

  • 按 3、1、2 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

  • 按 3、2、1 这样排列队伍,获得奖赏最多的大臣所获得金币数为9 。

     

因此,奖赏最多的大臣最少获得 2个金币,答案输出2 。

  • 贪心

本题为贪心题目,大家可以先在网上查阅贪心相关内容,这里仅做简单介绍。

贪心是一种在每次决策时采取当前意义下最优策略的算法,使用贪心法要求问题的整体最优性可以由局部最优性导出。贪心算法的正确使用需要证明,常见手法有:1.微扰 2.范围缩放 3.决策包容性 4.反证法 5.数学归纳法。

有《算法进阶竞赛指南》可以查阅本书第45页。

  • 解题思路

在读题,并经过实际操作后,数据的处理是这样的(国王的右手无用,最后一位大臣的左手无用)即最后一个大臣得到的金币为1*2*7/6=2。

按照每个大臣左、右手上的数的乘积小到大排序,就是最优排队方案。这个贪心算法,可以使用微扰法证明。

对于任意一种顺序,设n名大臣左、右手上的数分别是A[1]~A[n]与B[1]~B[n],国王手里的数是A[0]和B[0]。

如果我们交换相邻的两个大臣i与i+1,交换前这两个大臣得到的金币分别是:
                        \frac{1}{B[i]}*\prod_{j=0}^{i-1}A[j]              与        \frac{1}{B[i+1]}*\prod_{j=0}^{i}A[j]

交换之后这两个大臣获得的奖励是:

                        \frac{1}{B[i+1]}*\prod_{j=0}^{i-1}A[j]       与        \frac{A[i+1]}{B[i]}*\prod_{j=0}^{i-i}A[j]

  • 参考答案

#include <bits/stdc++.h>
#define int long long
//将int定义更改为long long
#define x first
#define y second
using namespace std;
typedef pair<int,int>pii;
//将pair<int,int>更名为pii
//typedef可以更改很多,可以自行查阅
const int N=1010;
pii p[N];

//由于int已被修改为long long
//应用signed定义main函数返回类型
signed main()
{
    int n;
    cin>>n;
    for(int i=0;i<=n;i++)
    {
        int a,b;
        cin>>a>>b;
        //使得p[].x中存储a*b即大臣左右手乘积
        p[i].x=a*b,p[i].y=a;
    }
    //快排(按照pair结构中第一个出现的数,由小到大排序)
    sort(p+1,p+n+1);
    int res=0,ans=1;
    for(int i=0;i<=n;i++)
    {   //在计算乘积之前应注意的是,p[].x存储了左右手乘积,每次运算应首先除以该大臣右手
        if(i) res=max(res,ans/(p[i].x/p[i].y));
        ans=ans*p[i].y;
    }
    cout<<res<<endl;
    return 0;
}

在 ABAP 中,`CL_SALV_TABLE` 是一个强大的类,用于展示和配置 ALV(ABAP List Viewer)表格。它提供了丰富的功能,如显示数据、设置功能按钮、列优化、布局配置以及异常处理等。 ### 显示数据 要使用 `CL_SALV_TABLE` 显示数据,可以通过调用 `CL_SALV_TABLE=>FACTORY` 方法来创建一个实例,并传递数据表作为参数。以下是一个简单的示例: ```abap DATA: lo_salv TYPE REF TO cl_salv_table, gt_data TYPE TABLE OF sflight. CALL METHOD cl_salv_table=>factory IMPORTING r_salv_table = lo_salv CHANGING t_table = gt_data. lo_salv->get_functions_base( )->set_all( ). lo_salv->display( ). ``` 在这个例子中,`gt_data` 是包含数据的内部表,`lo_salv` 是创建的 `CL_SALV_TABLE` 实例。通过调用 `get_functions_base()->set_all()` 可以启用所有默认功能按钮,最后调用 `display()` 方法来显示 ALV 表格 [^3]。 ### 设置函数 `CL_SALV_TABLE` 提供了多种方法来设置功能按钮。例如,可以禁用或启用特定的功能,或者添加自定义功能。以下是如何设置功能按钮的示例: ```abap DATA: lo_functions TYPE REF TO cl_salv_functions_list. lo_functions = lo_salv->get_functions_list( ). lo_functions->set_function_visible( if_salv_c_function=>export ). lo_functions->set_function_enabled( if_salv_c_function=>print, abap_false ). ``` 在这个例子中,`get_functionsList()` 方法获取功能列表,`set_function_visible()` 方法设置特定功能为可见,而 `set_function_enabled()` 方法则可以启用或禁用特定功能 [^2]。 ### 列优化 列优化包括调整列宽、设置列标题、隐藏列等操作。可以通过 `CL_SALV_COLUMNS_TABLE` 类的方法来实现这些设置: ```abap DATA: lo_columns TYPE REF TO cl_salv_columns_table. lo_columns = lo_salv->get_columns( ). " 设置列宽 lo_columns->set_optimize( if_salv_c_bool=>true ). " 设置列标题 lo_columns->get_column( 'CARRID' )->set_short_text( 'Airline' ). " 隐藏列 lo_columns->get_column( 'CONNID' )->set_visible( if_salv_c_bool=>false ). ``` 上述代码展示了如何优化列宽、更改列标题以及隐藏特定列 [^1]。 ### 布局配置 布局配置涉及保存和恢复用户的视图设置,比如列顺序、宽度和排序等。这可以通过 `CL_SALV_LAYOUT` 类来完成: ```abap DATA: lo_layout TYPE REF TO cl_salv_layout. lo_layout = lo_salv->get_layout( ). lo_layout->set_key( 'MY_LAYOUT_KEY' ). lo_layout->set_default( if_salv_c_bool=>true ). lo_layout->save( ). ``` 在这个例子中,`set_key()` 方法设置了布局的标识符,`set_default()` 方法将当前布局设为默认布局,而 `save()` 方法则保存了当前的布局设置 [^1]。 ### 异常处理 在使用 `CL_SALV_TABLE` 时,可能会遇到一些异常情况,比如数据不一致或无效的操作。为了处理这些异常,可以使用 TRY-CATCH 块来捕获并处理异常: ```abap TRY. CALL METHOD cl_salv_table=>factory IMPORTING r_salv_table = lo_salv CHANGING t_table = gt_data. CATCH cx_salv_msg INTO DATA(lx_msg). " 处理异常 WRITE: / 'Error creating SALV table:', lx_msg->get_text( ). ENDTRY. ``` 在这个 TRY-CATCH 块中,如果创建 `CL_SALV_TABLE` 实例时发生错误,则会捕获到 `cx_salv_msg` 类型的异常,并输出错误信息 [^1]。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊猫眼101

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值