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;
}
相关推荐
jimy19 小时前
构造函数表达式的值类别是:prvalue
开发语言·c++
wuminyu9 小时前
JVM规范学习总结-Class文件结构
java·linux·c语言·jvm·c++
多弗朗皮卡丘9 小时前
C++特殊类设计
开发语言·c++·设计模式
志起计算机编程9 小时前
Clickhouse的几个关键优势
算法
重生之小比特10 小时前
【算法拾光 7】双指针|两数之和 II - 输入有序数组 + 三数之和
算法
Navigator_Z10 小时前
LeetCode //C - 1304. Find N Unique Integers Sum up to Zero
c语言·算法·leetcode
Yyyyyy~10 小时前
【C++】String
c++
会编程的小孩19 小时前
C++ qt的安装
c++
企业数字化笔记21 小时前
视频人体姿态怎么做三维可视化?2D关键点、深度局限与技术选型
人工智能·算法·音视频