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\n",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\n",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\n",ans);
    return 0;
}

时间: 2024-10-16 10:47:54

Codeforces Round #327 (Div. 1) D. Top Secret Task的相关文章

Codeforces Round #327 (Div. 2)-Wizards&#39; Duel

题意: 在一条长度为l的走廊,两个人站在走廊的左右两端分别以p,q的速度走来,问他们相遇时离左端的距离是多少? 思路: 非常简单的暴力题,不解释. 代码如下: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <fstream> 5 #include <ctime> 6 #include <cmath> 7 #include <cs

Codeforces Round #327 (Div. 1), problem: (A) Median Smoothing

http://codeforces.com/problemset/problem/590/A: 在CF时没做出来,当时直接模拟,然后就超时喽. 题意是给你一个0 1串然后首位和末位固定不变,从第二项开始到倒数第二项,当前的a[i]=(a[i-1],a[i],a[i+1])三项排序后的中间项,比如连续3项为 1 0 1,那么中间的就变为1,然后题目让你输出达到稳定状态时所需的最小步数,不能的话输出-1. 无论给你啥数列,都能达到稳态.所以不可能输出-1: 还有一开始就稳定不变,或经过几次变换而稳定

Codeforces Round #327 (Div. 2) B Rebranding

1 /* 2 3 自从做了DP专题就没做cf惹,然而并没有什么用哇= =dp还是没啥赶脚,cf也欠了一大堆哇,还是渣渣哦多克! 4 题意: 5 给出字符串长度和要互换的字母组数,求互换后的串. 6 把每个字母最后换成啥保存起来最后输出即可. 7 */ 8 #include<cstdio> 9 #include<algorithm> 10 #include<cstring> 11 using namespace std; 12 const int maxn=200005;

Codeforces Round #327 (Div. 2) B. Rebranding C. Median Smoothing

B. Rebranding The name of one small but proud corporation consists of n lowercase English letters. The Corporation has decided to try rebranding — an active marketing strategy, that includes a set of measures to change either the brand (both for the

暴搜 - Codeforces Round #327 (Div. 2) E. Three States

E. Three States Problem's Link Mean: 在一个N*M的方格内,有五种字符:'1','2','3','.','#'. 现在要你在'.'的地方修路,使得至少存在一个块'1','2'和'3'是连通的. 问:最少需要修多少个'.'的路. analyse: 想法题,想到了就很简单. 直接暴力枚举每个国家到每个可达的点的最小代价,然后计算总和取最小值. dis[k][x][y]表示第k个国家到达坐标(x,y)的点的最小代价. Time complexity: O(N) vi

Codeforces Round #327 (Div. 2) B. Rebranding 模拟

B. Rebranding The name of one small but proud corporation consists of n lowercase English letters. The Corporation has decided to try rebranding — an active marketing strategy, that includes a set of measures to change either the brand (both for the

Codeforces Round #327 (Div. 2)C. Median Smoothing 构造

C. Median Smoothing A schoolboy named Vasya loves reading books on programming and mathematics. He has recently read an encyclopedia article that described the method of median smoothing (or median filter) and its many applications in science and eng

随笔—邀请赛前训—Codeforces Round #327 (Div. 2) Rebranding

题意:一个字符串,做n次变换,每次变换是把a字符与b字符全部调换.求全部调换完成后的字符串. 这道题目我一开始理解错意思了,理解成将所有a字符变成b字符,我觉得这样出貌似还更有挑战性一点..口亨 #include<cstdio> #include<cstring> #include<map> #include<iostream> using namespace std; #define MAX(x,y) (((x)>(y)) ? (x) : (y))

E. Three States - Codeforces Round #327 (Div. 2) 591E(广搜)

题目大意:有一个M*N的矩阵,在这个矩阵里面有三个王国,编号分别是123,想知道这三个王国连接起来最少需要再修多少路. 分析:首先求出来每个王国到所有能够到达点至少需要修建多少路,然后枚举所有点求出来最少的即可. 代码如下: --------------------------------------------------------------------------------------------------------- #include<stdio.h> #include<