老夫聊发少年狂,碱金属,丢池塘。浮溶游响,激起千朵浪。氢锂钠钾铷铯钫|

Yaosicheng124

园龄:1年3个月粉丝:8关注:11

CF 1839 D

题目描述

给定 N 个不同颜色的小球。你可以进行以下操作:

  • 插入一个颜色为 0 的小球,此操作最多执行 k 次。
  • 选择一个非零球,使得该球与至少一个 0 小球相邻。并把该小球移动到任意位置。这样会花费 1 的代价。

对于每个 1kN 求出将序列变成一个去除 0 后升序的序列所需最小代价。

思路

定义 dpi,j 表示把 [1,i] 排序,使用 j0 小球所需的最小代价。

如果 ai>ai1,那么我们有转移 dpi,jdpi1,j

否则,对于所有 0k<i1ak<ai,那么我们有 dpi,jdpk,j1+ik1,因为此时使用了一个 0 球,并且除端点外区间中每个点都需要移动一次。

空间复杂度 O(N2),时间复杂度 O(N3)

代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 505, INF = MAXN;

int t, n, a[MAXN], dp[MAXN][MAXN], ans;

void Solve() {
  cin >> n;
  for(int i = 1; i <= n; ++i) {
    cin >> a[i];
  }
  for(int i = 0; i <= n + 1; ++i) {
    for(int j = 0; j <= n; ++j) {
      dp[i][j] = INF;
    }
  }
  dp[0][0] = 0, a[n + 1] = n + 1;
  for(int i = 1; i <= n + 1; ++i) {
    for(int j = 0; j <= n; ++j) {
      if(a[i] > a[i - 1]) {
        dp[i][j] = dp[i - 1][j];
      }
      if(j) {
        for(int k = 0; k < i - 1; ++k) {
          if(a[k] < a[i]) {
            dp[i][j] = min(dp[i][j], dp[k][j - 1] + i - k - 1);
          }
        }
      }
    }
  }
  ans = dp[n + 1][0];
  for(int i = 1; i <= n; ++i) {
    ans = min(ans, dp[n + 1][i]);
    cout << ans << " \n"[i == n];
  }
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  for(cin >> t; t--; Solve()) {
  }
  return 0;
}

本文作者:Yaosicheng124

本文链接:https://www.cnblogs.com/yaosicheng124/p/18416688

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Yaosicheng124  阅读(13)  评论(0编辑  收藏  举报
  1. 1 Minecraft C418
Minecraft - C418
00:00 / 00:00
An audio error has occurred.

暂无歌词

加载中…

{{tag.name}}

{{tran.text}}{{tran.sub}}
无对应文字
有可能是
{{input}}
尚未录入,我来提交对应文字
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起