CodeForces - 714E + POJ - 3666 (dp严格单调递增与非严格单调递增)

47 篇文章 0 订阅

POJ - 3666 :

此题是dp非严格单调递增的最小花费,要满足非严格递增,即后一个要大于等于前一个数,现在要求n个数的非严格递增前i个数的花费肯定是前i-1个数花费,再加上第i个数的花费,前i-1个数之能是第i-1个数小于等于第i个数的情况,所以dp转移为:

dp[i][j]=abs(a[i]-j)+min{dp[i-1][k<=j]};

就是说你要取i-1个数最后一个数比j小的情况,那这范围大了去了,网上说离散化,意思就是把这些数限制在他给的n个数中。

具体原因也不是很清楚。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=2010;
int dp[N][N];
int a[N], b[N];


int main()
{
    int n;
    scanf("%d", &n);
    for(int i=1; i<=n; i++)
    {
         scanf("%d", a+i);
         b[i]=a[i];
    }

    sort(a+1, a+1+n);
   
    memset(dp, 0x3f, sizeof(dp));
    memset(dp[0], 0, sizeof(dp[0]));
    for(int i=1; i<=n; i++)
    {
        int mm=INF;
        for(int j=1; j<=n; j++)
        {
            mm=min(mm, dp[i-1][j]);
            dp[i][j]=mm+abs(b[i]-a[j]);
        }
    }
  
    int ans=INF;
    for(int i=1; i<=n; i++)
        ans=min(ans, dp[n][i]);
    printf("%d\n", ans);

    return 0;
}

CodeForces - 714E:

这个题是严格递增,如果非严格递增,那么就要求a[j]-a[i]>=j-i (j>i),  即a[j]-j>=a[i]-i, 就是说他给的n个数减去他的下标,求该n个数的非严格递增。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n;
ll a[3010], b[3010];
ll cos=INF;
ll dp[3010][3010];

int main(){
    scanf("%d", &n);

    for(int i=1; i<=n; i++)
    {
        scanf("%lld", &a[i]);
        a[i]-=i;
        b[i]=a[i];
    }
    sort(b+1, b+1+n);

    ll mm;
    memset(dp, 0x3f, sizeof(dp));
    memset(dp[0], 0, sizeof(dp[0]));
    for(int i=1; i<=n; i++){
        mm=INF;
        for(int j=1; j<=n; j++){
            mm=min(dp[i-1][j], mm);
            dp[i][j]=abs(b[j]-a[i])+mm;
        }
    }
    mm=INF;
    for(int i=1; i<=n; i++)
        mm=min(dp[n][i], mm);
    printf("%lld\n", mm);

    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值