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;
}
相关推荐
码客-ygluu32 分钟前
X3 LUA 异步分布式微服务集群框架
c++·架构·lua
forest_093 小时前
多 Agent 协作第二课:交叉验证≠独立验证
人工智能·python·算法·机器学习·prompt·agi
九英里路3 小时前
protobuf快速上手
网络·c++·中间件·json·谷歌·序列化·protobuf
纪念 2294 小时前
C++ 算法基础 (差分)
开发语言·c++·算法
jyOverQ7 小时前
从零学 JVM(六):垃圾回收算法详解——标记清除、标记复制与标记整理
jvm·算法
ShineWinsu9 小时前
对于Qt:QTreeWidget常见属性以及QTreeWidgetItem类的解析
开发语言·c++·qt·gui·客户端·多叉树·qtreewidget
严肃小白兔9 小时前
第 06/24 期:神经网络的反向传播算法:从链式法则到梯度计算
人工智能·神经网络·算法
落羽的落羽9 小时前
【C++】C++17的主要特性
linux·服务器·开发语言·c++·算法·机器学习
【心态好不摆烂】10 小时前
数据结构基础精讲3
数据结构·算法