codeforces 435 B. Pasha Maximizes 解题报告

本文讨论了如何使用贪心策略解决Codeforces上的排序问题。通过限制交换次数,作者详细解释了如何将较大数字尽可能地移动到高位,以形成最大的数。文章通过实例演示了贪心算法的应用,并提供了C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://codeforces.com/problemset/problem/435/B

题目意思:给出一个最多为18位的数,可以通过对相邻两个数字进行交换,最多交换 k 次,问交换 k 次之后,这个数最大可以变成多少。

      不知道最近是不是疏于训练(一直研究百度之星的题目,最终决定就是暂时放下,可能能力还没达到做那种题目的水平,不过都好感谢乌冬兄耐心甘为我解答左两道题目),昨晚又想学学拓扑排序(SPFA提到),结果没看明白= =...再加上昨晚比赛...电脑卡机卡得要命,于是悲催了= =

      这个是赛后做的......做的时候不知道怎么在尽可能贪心和k次这个约束条件下取舍...看了别人的,一下子豁然开朗,晚上一打即过,哈哈哈....

      大方向就是要往贪心的策略来想。怎样贪心?当然是把位数越大的数字越往高位移动,这样保证最终得到的数尽量大,但是,有一个关键的约束条件,就是不能超过 k 次,暗含的意思就是,装载着数字比较大的位,移动到高位的距离不能超过 k 这个长度。 

      以这组数据为例:

      由于最高位的数字 9 是最大的,所以没必要讨论该位。那么从第二位数字0开始,后面的位中最大的那个数是第三位的9,将它与第二位数字交换,变成9900000078001234,次数从6变为5(因为交换了一次)....接着问题出现了,第三位的0究竟是拿最大的8(符合贪心的策略)不断与前面的数交换,还是拿次小的7不断与前面的数交换呢?如果是8,当交换5次之后,结果变成9900800007001234,而如果用7交换,结果变成9907000008001234,明显是后面的数比较大。

       所以贪心不能乱贪,前提条件就是紧紧地遵循交换次数最多不能超过当前允许的次数。

     

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 const int maxn = 18 + 5;
 9 char s[maxn];
10 
11 int main()
12 {
13     int k;
14     while (cin >> s >> k)
15     {
16         int len = strlen(s);
17         for (int i = 0; i < len; i++)
18         {
19             int t = i;      // 讨论第i位的数,后面有没有更大的数可以替代它
20             for (int j = i+1; j < len && j-i <= k; j++)   // j-i <= k就是满足交换次数(实质就是j到i的距离)不能超过剩下最多能交换的次数k
21             {
22                 if (s[j] > s[t])
23                     t = j;     // 找出最大数的下标,前提是不超过k的次数
24             }
25             k -= (t-i);
26             while (t != i)   // 代表找到比要讨论的当前最高位要大的数
27             {
28                 swap(s[t], s[t-1]);   // 不断向前交换
29                 t--;
30             }
31         }
32         cout << s << endl;
33     }
34     return 0;
35 }

 

      

转载于:https://www.cnblogs.com/windysai/p/3762799.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值