CF1839D Ball Sorting
  YdxfFsjpYokY 2023年11月02日 54 0


也许更好的阅读体验

CF1839D Ball Sorting_ci
CF1839D Ball Sorting_ci_02 个球排成一列,每个球都有自己的颜色,每个球的颜色都互不相同,且均在CF1839D Ball Sorting_ci_03范围内,第 CF1839D Ball Sorting_#include_04 个球的颜色为 CF1839D Ball Sorting_算法_05。你需要将这些球重新排序使得第 CF1839D Ball Sorting_#include_04 个球的颜色为 CF1839D Ball Sorting_#include_04。另外,你还有 CF1839D Ball Sorting_算法_08 个颜色为 CF1839D Ball Sorting_ci_09

由于这些球的性质特殊,你只能通过以下两种方式将他们排序:

  1. 将一个颜色为CF1839D Ball Sorting_#include_10 的球插入到序列中的任意一个位置。显然你只能执行这种操作 CF1839D Ball Sorting_算法_11 次,因为你只有 CF1839D Ball Sorting_算法_11 个颜色为 CF1839D Ball Sorting_#include_10
  2. 选择一个和零球相邻的非零球,将其取出并放到序列中的任意一个位置。每执行一次这种操作将会产生 CF1839D Ball Sorting_ci_14

你可以以任意顺序执行这些操作,在所有操作完成后,所有颜色为 CF1839D Ball Sorting_ci_09

对所有的 CF1839D Ball Sorting_ci_16求出答案。

CF1839D Ball Sorting_#include_17

  • 考虑CF1839D Ball Sorting_#include_10放在某个位置后,如果有一个数不在CF1839D Ball Sorting_#include_10旁边,并且想让这个CF1839D Ball Sorting_#include_10来取出,那么必须把之间的球都取走
  • 取出的球不用管,最后再放进来即可
  • 只要在若干次取球操作后,剩下的数是单增的即可
  • 每次取球都是取一个区间,一个CF1839D Ball Sorting_#include_10可取一个区间

根据以上几点,可以将问题转化成
一个长度为CF1839D Ball Sorting_ci_02的排列,允许最多取走CF1839D Ball Sorting_算法_23个没有交集的连续区间,使得剩下的数是单增的,代价是取走的区间的总长度,要求代价最小是多少
考虑在最前面插入一个数大小为CF1839D Ball Sorting_ci_09,最后面插入一个数大小为CF1839D Ball Sorting_ci_25,这两个数最后一定会留下,因为没有取走的必要
CF1839D Ball Sorting_ci_26表示第CF1839D Ball Sorting_#include_04个数没有被取走,取了CF1839D Ball Sorting_ci_28个区间使得前CF1839D Ball Sorting_#include_04个数剩下单增所需最小代价
考虑转移方程,枚举CF1839D Ball Sorting_ci_30,找到CF1839D Ball Sorting_acm_31,将CF1839D Ball Sorting_#include_32之间的数全部取走
因此有当CF1839D Ball Sorting_acm_33时,CF1839D Ball Sorting_ci_34
CF1839D Ball Sorting_dp_35时,CF1839D Ball Sorting_ci_36
因为插入了CF1839D Ball Sorting_ci_25并且CF1839D Ball Sorting_ci_25肯定是没有被取走的,所以最后的答案就是CF1839D Ball Sorting_算法_39
CF1839D Ball Sorting_算法_40

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 505;
int T, n, top;
int a[maxn];
int f[maxn][maxn];
int main()
{
    cin >> T;
    while (T--) {
        cin >> n;
        for (int i = 1; i <= n; ++i)    cin >> a[i];
        a[n + 1] = n + 1;
        memset(f, 0x3f, sizeof(f));
        f[0][0] = 0;
        for (int i = 1; i <= n + 1; ++i)
            for (int j = 0; j <= i; ++j) {
                if (j)  f[i][j] = f[i][j - 1];
                for (int k = 0; k < i; ++k)
                    if (a[k] < a[i]) {
                        if (k == i - 1) f[i][j] = min(f[i][j], f[k][j]);
                        else if (j)  f[i][j] = min(f[i][j], f[k][j - 1] + i - k - 1);
                    }
            }
        for (int i = 1; i <= n; ++i)    cout << f[n + 1][i] << " \n"[i == n];
    }
    return 0;
}

如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
YdxfFsjpYokY