UVA-11491 奖品的价值 题解答案代码 算法竞赛入门经典第二版

GitHub - jzplp/aoapc-UVA-Answer: 算法竞赛入门经典 例题和习题答案 刘汝佳 第二版

又是一个情况复杂一点的题目。题目要求去掉元素,使剩下的数字最大,实际做法是从原序列中挑选数字,使得挑选后新序列的数字最大。

当原序列中剩余元素可以覆盖整个新序列时,最前面的元素肯定是最大的,即可能为多个9,后面的元素是8, 7等。所以这是一个从前向后越来越小的序列。这里使用第一个map存放,分别记录每个数字的起点和终点。

注意当新的更大的数字放置在对应位置时,新序列后面的位置的数字由于在原序列比这个更大的数字更早,因此不能存在,需要全部删掉。

考虑剩余元素可以不覆盖整个新序列时。如果它在新序列从后向前的位置比在原序列短,即这个元素后面还有冗余位置可以填充,那就走前面可以覆盖的流程即可。

如果它在新序列从后向前的位置比在原序列长,即这个元素如果按照排序填充的话,后面的元素数将会不够,这时候这个元素必然会填充到新序列的位置是:原序列从后向前的位置。且他后面的所有元素都复制到新序列中作为后续元素。这里使用了第二个map记录。

最后输出时,注意第一个map中的数据可能并不是完整的新序列数据,且第二个map是覆盖逻辑,优先级更高,因此这里使用序号遍历,从两个map中分别找。

AC代码

cpp 复制代码
#include <stdio.h>
#include <map>
#define MAXN 100005
using namespace std;

// beg 起始位置 end 终点的下一个位置
struct Stru
{
  int beg, end;
};

char s1[MAXN];
int n, d;
int s2[MAXN];
int s2len;
map<int, Stru> mp;
map<int, int> mp2;

// 调试输出
void outMap()
{
  printf("mp:\n");
  for (auto ip = mp.begin(); ip != mp.end(); ++ip)
  {
    printf("i:%d  beg:%d  end:%d \n", ip->first, ip->second.beg, ip->second.end);
  }
  printf("mp2:\n");
  for (auto ip = mp2.begin(); ip != mp2.end(); ++ip)
  {
    printf("v:%d  i:%d \n", ip->first, ip->second);
  }
  putchar('\n');
}

// 尾部所有元素一一对应
void setTail(int i)
{
  int j;
  mp2[s2len - (n - i)] = s1[i];
  for (j = i + 1; j < n; ++j)
    mp2[s2len - (n - j)] = s1[j];
}

void computed()
{
  int i, c1;
  for (i = 0; i < n; ++i)
  {
    if (mp.count(s1[i]))
    {
      if (s2len - mp[s1[i]].end <= 0)
        continue;
      if (s2len - mp[s1[i]].end >= n - i)
      {
        setTail(i);
        return;
      }
      mp[s1[i]].end = mp[s1[i]].end + 1;
      for (c1 = s1[i] - 1; c1 >= 0; --c1)
      {
        if (mp.count(c1))
          mp.erase(c1);
      }
    }
    else
    {
      for (c1 = s1[i] + 1; c1 <= 9; ++c1)
      {
        if (mp.count(c1))
        {
          if (s2len - mp[c1].end <= 0)
            break;
          if (s2len - mp[c1].end >= n - i)
          {
            setTail(i);
            return;
          }
          mp[s1[i]] = {mp[c1].end, mp[c1].end + 1};
          break;
        }
      }
      if (c1 > 9)
      {
        if (s2len >= n - i)
        {
          setTail(i);
          return;
        }
        else
          mp[s1[i]] = {0, 1};
      }
      for (c1 = s1[i] - 1; c1 >= 0; --c1)
      {
        if (mp.count(c1))
          mp.erase(c1);
      }
    }
    // printf("-- i: %d \n", i);
    // outMap();
  }
}

void outputRes()
{
  int i, j;
  for (i = 0; i < s2len; ++i)
  {
    if (mp2.count(i))
    {
      putchar(mp2[i] + '0');
      continue;
    }
    for (j = 9; j >= 0; --j)
    {
      if (!mp.count(j))
        continue;
      if (i >= mp[j].beg && i < mp[j].end)
        putchar(j + '0');
    }
  }
  putchar('\n');
}

int main()
{
  int i;
  while (scanf("%d %d", &n, &d) >= 2 && n > 0 && d > 0)
  {
    scanf("%s", s1);
    s2len = n - d;
    for (i = 0; i < n; ++i)
      s1[i] = s1[i] - '0';
    mp.clear();
    mp2.clear();
    computed();
    // outMap();
    outputRes();
  }
  return 0;
}
相关推荐
weixin_307779135 小时前
C++代码实现MATLAB中的dlarray函数功能
开发语言·c++·算法·matlab
Frank_refuel8 小时前
C++11之一场名为“搬家”的 C++ 之旅
开发语言·c++
hetao173383710 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法
Zootopia62611 小时前
飞行力学知识梳理1|飞行性能与稳定性
人工智能·python·算法·机器学习·无人机·学习方法·信息与通信
longlongzihan11 小时前
从LeetCode 70. 爬楼梯看动态规划:如何精准推导状态转移方程?
c++·算法·leetcode·动态规划
2601_9603563812 小时前
2027校招采购岗解析:数学基础如何迁移到需求预测、成本与供应商分析
人工智能·算法
h_a_o777oah13 小时前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
HEJOO913 小时前
指针的算术运算详解
java·数据结构·算法
Coder-magician13 小时前
《代码随想录》刷题打卡day47:并查集-part01
数据结构·算法·图论