ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ICPC North Central NA Contest 2017 D. Smooth Array —— DP,剪枝

2020-03-01 22:04:45  阅读:267  来源: 互联网

标签:剪枝 d% Central Contest int 位置 枚举 转移 dp


This way

题意:

输入是n,k,s,n表示当前序列长度,s表示任意连续的k个数和为s,你有一个操作,可以将任意一个位置上的数变成0-s中的任意一个数,你至少要操作几次能使得它满足s

题解:

将这个数组分成一段一段长度为k的串之后,每个串都是相同的。
那么就可以将其变成这样一个东西:
在这里插入图片描述
每列的数字都是相同的。它数据范围是5000,暗示我们n2n^2n2。那么dp[i][j]表示到第i个位置的时候,前面i列的和为j时最少需要转多少个位置。
那么最简单的想法就是到第i位的时候,枚举当前转换成什么位置,枚举dp[i-1],然后转移,这样是k^3的转移,过不去。
然后发现其实如果k很大,那么列数就很小,k很小,列数就很大。然后可以只枚举当前列有的数进行转移。对于没有的数,不用管它,一定是+第i列的所有位置的数量。所以这种情况就是再枚举一次dp[i][j](0<=j<=s)dp[i][j](0<=j<=s)dp[i][j](0<=j<=s),它可以从
dp[i1][k](0<=k<=j)dp[i-1][k](0<=k<=j)dp[i−1][k](0<=k<=j)转移过来。那么用mi数组维护dp[i-1]的前缀最小值。
状态转移方程就是

dp[i][j]=min(dp[i][j],mi[j]+num[i]);
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5;
int dp[N][N],mi[N],num[N],siz[N][N];
vector<int>vec[N];
int a[N];
int main()
{
    int n,k,s;
    scanf("%d%d%d",&n,&k,&s);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]),num[i%k]++;
        if(!siz[i%k][a[i]])
            vec[i%k].push_back(a[i]);
        siz[i%k][a[i]]++;
    }
    for(int i=0;i<=k;i++)
        for(int j=0;j<=s;j++)
            dp[i][j]=1e9;
    //memset(mi,125,sizeof(mi));
    for(int i=0;i<=s;i++){
        dp[0][i]=num[0]-siz[0][i];
        mi[i]=i?min(mi[i-1],dp[0][i]):dp[0][i];
    }
    for(int i=1;i<k;i++){
        for(auto j:vec[i]){
            for(int k=j;k<=s;k++)
                dp[i][k]=min(dp[i][k],dp[i-1][k-j]+num[i]-siz[i][j]);
        }
        for(int j=0;j<=s;j++)
            dp[i][j]=min(dp[i][j],mi[j]+num[i]);

        for(int j=0;j<=s;j++)
            mi[j]=j?min(mi[j-1],dp[i][j]):dp[i][j];
    }
    printf("%d\n",dp[k-1][s]);
    return 0;
}
/*
16 4 10
5 2 3 5 5 2 3 5 5 2 3 5 5 3 1 5
*/
天翼之城 发布了554 篇原创文章 · 获赞 31 · 访问量 5万+ 他的留言板 关注

标签:剪枝,d%,Central,Contest,int,位置,枚举,转移,dp
来源: https://blog.csdn.net/tianyizhicheng/article/details/104600786

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有