kuangbin专题十二 基础dp

kuangbin专题十二 基础dp

1. Max Sum Plus Plus

压缩一维避免超空间,维护前缀最大值将 O ( n 3 ) O(n^3) O(n3)降到 O ( n 2 ) O(n^2) O(n2)

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,INF=0x7fffffff;
int n,m;
int a[N],f[N],Max[N];
int main()
{
    while(scanf("%d%d",&m,&n)!=EOF){
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=0;i<=n;i++) f[i]=Max[i]=0;
        int cur;
        for(int j=1;j<=m;j++){
            cur=-INF;
            for(int i=j;i<=n;i++){
                f[i]=max(f[i-1],Max[i-1])+a[i];
                Max[i-1]=cur;
                cur=max(cur,f[i]);
            }
        }
        printf("%d\n",cur);
    }
    return 0;
}

2. Ignatius and the Princess IV

感觉像是题目放错了,用数组或者map记录个数就行。

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
const int N=1e6+10;
int n,a[N];
unordered_map<int,int> num;
int main()
{
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        num.clear();
        for(int i=1;i<=n;i++){
            num[a[i]]++;
            if(num[a[i]]>=(n+1)/2){
                printf("%d\n",a[i]);
                break;
            }
        }
    }
    return 0;
}

相邻的HDU 1028刚好是个dp。分别可以用完全背包或分治的做法来做。

#include<bits/stdc++.h>
using namespace std;
const int N=130;
int f[N];
void init(){
    f[0]=1;
    for(int i=1;i<N;i++)
        for(int j=i;j<N;j++)
            f[j]+=f[j-i];
}
int main()
{
    init();
    int n;
    while(scanf("%d",&n)!=EOF){
        printf("%d\n",f[n]);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=130;
int f[N][N];
int calc(int a,int b){
    if(f[a][b]!=-1) return f[a][b];
    if(a<1||b<1) return f[a][b]=0;
    if(a==1||b==1) return f[a][b]=1;
    if(a==b) return f[a][b]=1+calc(a,b-1);
    if(a<b) return f[a][b]=calc(a,a);
    if(a>b) return f[a][b]=calc(a-b,b)+calc(a,b-1);
}
int main()
{
    memset(f,-1,sizeof f);
    int n;
    while(scanf("%d",&n)!=EOF){
        printf("%d\n",calc(n,n));
    }
    return 0;
}

3. Monkey and Banana

最长上升子序列模型题

#include<bits/stdc++.h>
using namespace std;
const int N=200;
struct Block{
    int x,y,z;
    bool operator >(const Block &t)const{
        if(x!=t.x) return x>t.x;
        return y>t.y;
    }
};
int f[N];
int n;
int main()
{
    int T=0;
    while(scanf("%d",&n),n){
        vector<Block> v;
        for(int i=1;i<=n;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            v.push_back({a,b,c});
            v.push_back({a,c,b});
            v.push_back({b,a,c});
            v.push_back({b,c,a});
            v.push_back({c,a,b});
            v.push_back({c,b,a});
        }
        sort(v.begin(),v.end(),greater<Block>());
        int res=0;
        for(int i=0;i<v.size();i++){
            f[i]=v[i].z;
            for(int j=0;j<i;j++){
                if(v[i].x<v[j].x&&v[i].y<v[j].y){
                     f[i]=max(f[i],f[j]+v[i].z);
                }
            }
            res=max(res,f[i]);
        }
        printf("Case %d: maximum height = %d\n",++T,res);
    }
    return 0;
}

4. Doing Homework

很巧妙的状压dp。

#include<bits/stdc++.h>
using namespace std;
const int N=16;
struct Subject{
    char name[110];
    int last,d;
}a[N];
int n;
int f[1<<N],pre[1<<N];
void output(int u){
    if(pre[u]!=0) output(pre[u]);
    for(int i=0;i<n;i++){
        if(u>>i&1^pre[u]>>i&1){
            printf("%s\n",a[i].name);
            break;
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%s%d%d",a[i].name,&a[i].last,&a[i].d);
        memset(f,0x3f,sizeof f);
        f[0]=0;
        for(int i=0;i<1<<n;i++){
            int sum=0;
            for(int j=0;j<n;j++)
                if(i>>j&1) sum+=a[j].d;
            for(int j=0;j<n;j++){
                if(i>>j&1) continue;
                int temp=max(0,sum+a[j].d-a[j].last);
                int k=i|(1<<j);
                if(f[k]>f[i]+temp){
                    f[k]=f[i]+temp;
                    pre[k]=i;
                }
            }
        }
        printf("%d\n",f[(1<<n)-1]);
        output((1<<n)-1);
    }
    return 0;
}

5. Super Jumping! Jumping! Jumping!

最长上升子序列模板题

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int a[N],f[N];
int n;
int main()
{
    while(scanf("%d",&n),n){
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++){
            f[i]=a[i];
            for(int j=1;j<i;j++)
                if(a[i]>a[j]) f[i]=max(f[i],f[j]+a[i]);
        }
        printf("%d\n",*max_element(f+1,f+1+n));
    }
    return 0;
}

6. Piggy-Bank

完全背包恰好装满问题。

#include<bits/stdc++.h>
using namespace std;
const int N=510,M=10010,INF=0x3f3f3f3f;
int w[N],p[N];
int f[M];
int n,m;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        m-=n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d",&p[i],&w[i]);
        memset(f,0x3f,sizeof f);
        f[0]=0;
        for(int i=1;i<=n;i++)
            for(int j=w[i];j<=m;j++)
                f[j]=min(f[j],f[j-w[i]]+p[i]);
                
        if(f[m]==INF) puts("This is impossible.");
        else printf("The minimum amount of money in the piggy-bank is %d.\n",f[m]);
    }
    return 0;
}

7. 免费馅饼

二维线性dp, f [ i ] [ j ] f[i][j] f[i][j]表示在第 i i i秒位于 j j j最多能接到的馅饼数量。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,M=11;
int a[N][M];
int n;
int f[N][M];
int main()
{
    while(scanf("%d",&n),n){
        int m=0;
        memset(a,0,sizeof a);
        for(int i=0;i<n;i++){
            int x,t;
            scanf("%d%d",&x,&t);
            a[t][x]++;
            m=max(m,t);
        }
        memset(f,-0x3f,sizeof f);
        f[0][5]=0;
        for(int i=1;i<=m;i++){
            for(int j=0;j<=10;j++){
                f[i][j]=f[i-1][j]+a[i][j];
                if(j>0) f[i][j]=max(f[i][j],f[i-1][j-1]+a[i][j]);
                if(j<10) f[i][j]=max(f[i][j],f[i-1][j+1]+a[i][j]);
            }
        }
        printf("%d\n",*max_element(f[m],f[m]+11));
    }
    return 0;
}

8. Tickets

简单线性dp

#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int a[N],b[N];
int f[N];
int n;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<n;i++) scanf("%d",&b[i]);
        f[1]=a[1];
        for(int i=2;i<=n;i++) f[i]=min(f[i-1]+a[i],f[i-2]+b[i-1]);
        int hh=8,mm=0,ss=0;
        char str[3]="am";
        ss+=f[n];
        mm+=ss/60,ss%=60;
        hh+=mm/60,mm%=60;
        if(hh>=12) hh-=12,str[0]='p';
        printf("%02d:%02d:%02d %s\n",hh,mm,ss,str);
    }
    return 0;
}

9. 最少拦截系统

不上升子序列覆盖整个数组的最少个数等于最长子序列的长度。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N];
int f[N];
int n;
int main()
{
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        int len=1;
        f[1]=a[1];
        for(int i=2;i<=n;i++){
            if(a[i]>f[len]) f[++len]=a[i];
            else *lower_bound(f+1,f+1+len,a[i])=a[i];
        }
        printf("%d\n",len);
    }
    return 0;
}

10. FatMouse’s Speed

#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int f[N],pre[N],path[N];
struct Mouse{
    int id,w,s;
    bool operator <(const Mouse &t)const{
        if(w!=t.w) return w<t.w;
        return s>=t.s;
    }
}a[N];
void output(int u){
    if(pre[u]!=u) output(pre[u]);
    printf("%d\n",a[u].id);
}
int main()
{
    int n=1;
    while(scanf("%d%d",&a[n].w,&a[n].s)!=EOF) a[n].id=n,n++;
    n--;
    sort(a+1,a+1+n);
    int res=0,p=0;
    for(int i=1;i<=n;i++){
        pre[i]=i;
        f[i]=1;
        for(int j=1;j<i;j++){
            if(a[i].w>a[j].w&&a[i].s<a[j].s&&f[j]+1>f[i]){
                f[i]=f[j]+1;
                pre[i]=j;
            }
        }
        if(f[i]>res){
            p=i;
            res=f[i];
        }
    }
    printf("%d\n",res);
    output(p);
    return 0;
}

11. Jury Compromise

一道很麻烦的背包, f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]状态的含义是前 i i i个人种选 j j j个人差的和为 k k k的最大值。

因为记录方案需要三维,所以状态从三维降成两维感觉也没什么必要,降一维之后在memset的时候确实会快一点。

POJ的数据有点弱,有些假算法也会放过,最好到uva 323交一下。

三维状态
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int N=210,M=810;
int f[N][21][M],pre[N][21][M];
int a[N],b[N],sum[N],dif[N];
int n,m;
void output(int i,int j,int k){
    if(j==0) return;
    if(pre[i][j][k]==-1) output(i-1,j,k);
    else{
        output(i-1,j-1,k-dif[i]);
        printf(" %d",i);
    }
}
int main()
{
    int T=1;
    while(scanf("%d%d",&n,&m),n||m){
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i],&b[i]);
            sum[i]=a[i]+b[i];
            dif[i]=a[i]-b[i];
        }
        int offset=m*20;
        memset(f,-1,sizeof f);
        for(int i=0;i<=n;i++) f[i][0][offset]=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                for(int k=0;k<=2*offset;k++){
                    f[i][j][k]=f[i-1][j][k];
                    pre[i][j][k]=-1;
                    if(k-dif[i]>=0&&k-dif[i]<=2*offset&&f[i-1][j-1][k-dif[i]]!=-1){
                        int t=f[i-1][j-1][k-dif[i]]+sum[i];
                        if(f[i][j][k]<t){
                            pre[i][j][k]=1;
                            f[i][j][k]=t;
                        }
                    }
                }
            }
        }
        int p;
        for(p=0;p<=offset;p++)
            if(f[n][m][offset-p]!=-1||f[n][m][offset+p]!=-1)
                break;
        p=f[n][m][offset-p]>f[n][m][offset+p]?offset-p:offset+p;
        int x=f[n][m][p];
        int sum1=(x+(p-offset))/2,sum2=(x-(p-offset))/2;
        printf("Jury #%d\n",T++);
        printf("Best jury has value %d for prosecution and value %d for defence:\n",sum1,sum2);
        output(n,m,p);
        puts("\n");
    }
    return 0;
}

二维状态
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int N=210,M=810;
int f[21][M],pre[N][21][M];
int a[N],b[N],sum[N],dif[N];
int n,m;
void output(int i,int j,int k){
    if(j==0) return;
    if(pre[i][j][k]==-1) output(i-1,j,k);
    else{
        output(i-1,j-1,k-dif[i]);
        printf(" %d",i);
    }
}
int main()
{
    int T=1;
    while(scanf("%d%d",&n,&m),n||m){
        for(int i=1;i<=n;i++){
            scanf("%d%d",&a[i],&b[i]);
            sum[i]=a[i]+b[i];
            dif[i]=a[i]-b[i];
        }
        int offset=m*20;
        memset(f,-1,sizeof f);
        f[0][offset]=0;
        for(int i=1;i<=n;i++){
            for(int j=m;j>=1;j--){
                for(int k=0;k<=2*offset;k++){
                    pre[i][j][k]=-1;
                    if(k-dif[i]>=0&&k-dif[i]<=2*offset&&f[j-1][k-dif[i]]!=-1){
                        int t=f[j-1][k-dif[i]]+sum[i];
                        if(f[j][k]<t){
                            pre[i][j][k]=1;
                            f[j][k]=t;
                        }
                    }
                }
            }
        }
        int p;
        for(p=0;p<=offset;p++)
            if(f[m][offset-p]!=-1||f[m][offset+p]!=-1)
                break;
        p=f[m][offset-p]>f[m][offset+p]?offset-p:offset+p;
        int x=f[m][p];
        int sum1=(x+(p-offset))/2,sum2=(x-(p-offset))/2;
        printf("Jury #%d\n",T++);
        printf("Best jury has value %d for prosecution and value %d for defence:\n",sum1,sum2);
        output(n,m,p);
        puts("\n");
    }
    return 0;
}

12. Common Subsequence

最长公共子序列模板题

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e3+10;
char a[N],b[N];
int f[N][N];
int main()
{
    while(scanf("%s%s",a+1,b+1)!=EOF){
        int n=strlen(a+1);
        int m=strlen(b+1);
        memset(f,0,sizeof f);
        int res=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(a[i]==b[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+1);
                else f[i][j]=max(f[i-1][j],f[i][j-1]);
                res=max(res,f[i][j]);
            }
        }
        printf("%d\n",res);
    }
    return 0;
}

13. Help Jimmy

我是用从上往下dp的做法,要记录每个平台的左右端点下方是否有平台。

从下往上dp会方便一点,因为最终会汇聚到起点,可以少记录一些信息。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010,INF=0x3f3f3f3f;
struct Node{
    int x1,x2,h;
    bool operator <(const Node &t)const{
        return h>t.h;
    }
}a[N];
int l[N],r[N];
bool downl[N],downr[N];
int n,x,y,m;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d%d",&n,&x,&y,&m);
        for(int i=1;i<=n;i++)  scanf("%d%d%d",&a[i].x1,&a[i].x2,&a[i].h);
        sort(a+1,a+n+1);
        memset(l,0x3f,sizeof l);
        memset(r,0x3f,sizeof r);
        memset(downl,0,sizeof downl);
        memset(downr,0,sizeof downr);
        a[0]={x,x,y};
        l[0]=r[0]=0;
        for(int i=1;i<=n;i++){
            for(int j=0;j<i;j++){
                if(a[j].h>a[i].h&&a[j].h-a[i].h<=m){
                    if(a[j].x1>=a[i].x1&&a[j].x1<=a[i].x2&&!downl[j]){
                        l[i]=min(l[i],l[j]+abs(a[j].x1-a[i].x1)+a[j].h-a[i].h);
                        r[i]=min(r[i],l[j]+abs(a[j].x1-a[i].x2)+a[j].h-a[i].h);
                        downl[j]=true;
                    }
                    if(a[j].x2>=a[i].x1&&a[j].x2<=a[i].x2&&!downr[j]){
                        l[i]=min(l[i],r[j]+abs(a[j].x2-a[i].x1)+a[j].h-a[i].h);
                        r[i]=min(r[i],r[j]+abs(a[j].x2-a[i].x2)+a[j].h-a[i].h);
                        downr[j]=true;
                    }
                }
            }
        }

        int res=INF;
        for(int i=0;i<=n;i++){
            if(a[i].h>m) continue;
            if(!downl[i]) res=min(res,a[i].h+l[i]);
            if(!downr[i]) res=min(res,a[i].h+r[i]);
        }
        printf("%d\n",res);
    }
    return 0;
}

14. Longest Ordered Subsequence

最长上升子序列模板题

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int a[N],f[N];
int n;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int len=0;
    f[0]=-1;
    for(int i=1;i<=n;i++){
        if(a[i]>f[len]) f[++len]=a[i];
        else *lower_bound(f+1,f+1+len,a[i])=a[i];
    }
    cout<<len<<endl;
    return 0;
}

15. Treats for the Cows

简单区间dp, f [ i ] [ j ] f[i][j] f[i][j]表示选择左侧 i i i次和选择右侧 j j j次的最大值。

#include<iostream>
#include<algorithm>
using namespace std;
const int N=2010;
int f[N][N];
int a[N];
int n;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int len=1;len<=n;len++){
        for(int l=0;l<=len;l++){
            int r=len-l;
            if(l) f[l][r]=max(f[l][r],f[l-1][r]+a[l]*len);
            if(r) f[l][r]=max(f[l][r],f[l][r-1]+a[n-r+1]*len);
        }
    }
    int res=0;
    for(int i=0;i<=n;i++) res=max(res,f[i][n-i]);
    cout<<res<<endl;
    return 0;
}

16. FatMouse and Cheese

记忆化搜素,其中题意中的 k k k是指可以沿着某一方向最多走 k k k步。

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int a[N][N];
int f[N][N];
int n,m;
int nxt[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
vector<int> v[N][N];
int dfs(int x,int y){
    if(f[x][y]!=-1) return f[x][y];
    f[x][y]=0;
    for(int i=0;i<4;i++){
        for(int j=1;j<=m;j++){
            int tx=x+nxt[i][0]*j;
            int ty=y+nxt[i][1]*j;
            if(tx<1||tx>n||ty<1||ty>n) break;
            if(a[tx][ty]>a[x][y]) f[x][y]=max(f[x][y],dfs(tx,ty));
        }
    }
    return f[x][y]=f[x][y]+a[x][y];
}
int main()
{
    while(scanf("%d%d",&n,&m),n!=-1&&m!=-1){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
        memset(f,-1,sizeof f);
        printf("%d\n",dfs(1,1));
    }
    return 0;
}

17. Phalanx

dp的思路很巧妙,可以用哈希表加二分将 O ( n 3 ) O(n^3) O(n3)优化到 O ( n 2 l o g n ) O(n^2logn) O(n2logn)

O ( n 3 ) O(n^3) O(n3)
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
char g[N][N];
int f[N][N];
int n;
int main()
{
    while(scanf("%d",&n),n){
        for(int i=1;i<=n;i++) scanf("%s",g[i]+1);
        int res=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                int k=0;
                while(k<min(i,n-j+1)&&g[i-k][j]==g[i][j+k]){
                    k++;
                }
                if(i-1<1||j+1>n||k<=f[i-1][j+1]) f[i][j]=k;
                else f[i][j]=f[i-1][j+1]+1;
                res=max(res,f[i][j]);
            }
        }
        printf("%d\n",res);
    }
    return 0;
}
O ( n 2 l o g n ) O(n^2logn) O(n2logn)
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int N =1010,P=131;
ULL row[N][N],col[N][N],p[N];
char g[N][N];
int f[N][N];
int n;
void init(){
    p[0]=1;
    for(int i=1;i<N;i++) p[i]=p[i-1]*P;
}
void init_hash(){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            row[i][j]=row[i][j-1]*P+g[i][j]-'a';

    for(int i=n;i>=1;i--)
        for(int j=n;j>=1;j--){
            if(i==n) col[i][j]=g[i][j]-'a';
            else col[i][j]=col[i+1][j]*P+g[i][j]-'a';
        }
}
int main()
{
    init();
    while(scanf("%d",&n),n){
        for(int i=1;i<=n;i++) scanf("%s",g[i]+1);
        init_hash();
        int res=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                int l=1,r=min(i,n-j+1);
                while(l<r){
                    int mid=l+r+1>>1;
                    if(col[i-mid+1][j]-col[i+1][j]*p[mid]==row[i][j+mid-1]-row[i][j-1]*p[mid]) l=mid;
                    else r=mid-1;
                }
                if(i-1<1||j+1>n||l<=f[i-1][j+1]) f[i][j]=l;
                else f[i][j]=f[i-1][j+1]+1;
                res=max(f[i][j],res);
            }
        }
        printf("%d\n",res);
    }
    return 0;
}

18. Milking Time

简单的线性dp, O ( n + m ) O(n+m) O(n+m)或者 O ( m 2 ) O(m^2) O(m2)的做法都可以。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e6+10,M=1010;
struct Node{
    int st,ed,v;
    bool operator<(const Node &t)const{
        return ed<t.ed;
    }
}a[M];
int f[N];
int n,m,k;
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&a[i].st,&a[i].ed,&a[i].v);
        a[i].ed+=k;
    }
    sort(a+1,a+1+m);
    int res=0;
    for(int i=0,j=1;i<=n+k;i++){
        while(j<=m&&a[j].ed<=i){
            if(f[a[j].st]+a[j].v>res) res=f[a[j].st]+a[j].v;
            j++;
        }
        f[i]=res;
    }
    printf("%d\n",res);
    return 0;
}

19. Making the Grade

因为最优解中每个数只会变成序列中的数,对 n n n个数去重之后进行 O ( n 2 ) O(n^2) O(n2)的dp就行了。

还有一种 O ( n l o g n ) O(nlogn) O(nlogn)的做法,感觉是碰到了也想不出来的存在,有兴趣的可以看这篇博客

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
const int N=2010;
LL f[N][N];
int n,a[N];
vector<int> v;
int main()
{
    scanf("%d",&n);

    v.push_back(-1);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        v.push_back(a[i]);
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    int m=v.size()-1;
    for(int i=1;i<=n;i++){
        LL Min=f[i-1][1];
        for(int j=1;j<=m;j++){
            Min=min(Min,f[i-1][j]);
            f[i][j]=Min+abs(a[i]-v[j]);
        }
    }
    LL res=1e18;
    for(int i=1;i<=m;i++) res=min(res,f[n][i]);
    printf("%lld\n",res);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值