zoukankan      html  css  js  c++  java
  • Codeforces Round #327 (Div. 1) D. Top Secret Task

    题意: 给了一个n,k,s,和一个数组,求使用小于s次的交换使得前k个整数的和尽可能的小,交换指的的是相邻的两个数交换,

    首先考虑 如果最小的k个数全部再最后面,那么至少要花费 ( n - k + 1 + n)*k/2 - (( k + 1 ) * k / 2) 这么多下才能把这k个数搬运到最前面,也就是说如果s他大于等于这个数 那么答案一定是最小的那k个数,

    否则进行下面的做法

    假设前k个数 在最初的 那个数组中的下标分别是L1<L2<...<Lk,肯定被选中的那k个数他们的相对位置肯定是不变得,如果变了会增加交换的次数

    那么我们就假设就是最初给的那个数组的下标L1 L2 L3 L4..Lk 那么所要的交换此时就是 T=L1-1+L2-2+...Lk-k我们知道这个要小于等于S

    于是得到 L1+L2+...+Lk<=S+(1+k)*k/2,采用dp[i][j][p]表示 前i个数 选了j个他们的下标和为p的最小值,dp[i][j][p]=min(dp[i-1][j][p],dp[i-1][j-1][p-i]+A[i])

    数据太大 采用滚动数组,

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <string.h>
    using namespace std;
    const int maxn=155;
    const int INF=2147483647;
    int A[maxn];
    int dp[2][maxn][maxn*maxn*2];
    int main()
    {
    
        int n,k,s;
        scanf("%d%d%d",&n,&k,&s);
        for(int i=1; i<=n; i++)
            scanf("%d",&A[i]);
        if(k==n)
        {
           int sum=0;
           for(int i=1; i<=n; i++)
            sum+=A[i];
           printf("%d
    ",sum);return 0;
        }
        if( s >= ( n - k + 1 + n)*k/2 - (( k + 1 ) * k / 2 ) )
        {
            sort(A+1,A+1+n);
            int sum=0;
            for(int i=1; i<=k; i++)
                sum+=A[i];
            printf("%d
    ",sum);return 0;
        }
        int S=s+(k+1)*k/2;
        int cur=0,per=1;
        for(int i=1; i<=k; i++)
            for(int j=0; j<=S; j++)dp[0][i][j]=INF;
    
        for(int i=1; i<=n; i++)
        {
            cur^=1;
            per^=1;
            for(int j=1; j<=k; j++)
            {
                for(int a=0; a<=S; a++)
                {
                    dp[cur][j][a]=dp[per][j][a];
                    if(a>=i&&dp[per][j-1][a-i]!=INF){
                      dp[cur][j][a]=min(dp[per][j-1][a-i]+A[i],dp[cur][j][a]);
                    }
                }
            }
        }
        int ans=INF;
        for(int i=0; i<=S; i++)
            ans=min(dp[cur][k][i],ans);
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    springcloud中常用的注解
    MySQL--Profiling和Trace使用
    MySQL Execution Plan--IN查询计划
    MySQL Config--参数system_time_zone和参数time_zone
    MySQL Replication--全局参数gtid_executed和gtid_purged
    MySQL Transaction--事务无法正常回滚导致的异常
    MySQL Execution Plan--数据排序操作
    MySQL Session--批量KILL会话
    MySQL Transaction--MySQL与SQL Server在可重复读事务隔离级别上的差异
    MySQL Transaction--事务相关查询
  • 原文地址:https://www.cnblogs.com/Opaser/p/4931563.html
Copyright © 2011-2022 走看看