zoukankan      html  css  js  c++  java
  • 动态规划练习们~

    先学习了一下状丫 找了几个比较简单的题

    /*codevs 2596 售货员难题 状丫dp */
    #include<cstdio>
    #include<cstring>
    #define maxn 50010
    using namespace std;
    int n,g[20][20],f[maxn][20],ans;
    int min(int x,int y){
        return x<y?x:y;
    }
    int main()
    {
        scanf("%d",&n);n--;
        memset(f,127/3,sizeof(f));
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                scanf("%d",&g[i][j]);
        ans=f[0][0];f[0][0]=0;
        for(int i=1;i<(1<<n);i++)
            for(int j=1;j<=n;j++)if(i&(1<<j-1))
                for(int k=0;k<=n;k++)
                    f[i][j]=min(f[i][j],f[i-(1<<j-1)][k]+g[k][j]);
        for(int i=1;i<=n;i++)
            ans=min(ans,f[(1<<n)-1][i]+g[i][0]);
        printf("%d
    ",ans);
        return 0;
    }
    /*codevs 2800 送外卖 状丫dp 有个数据有点问题 2333*/
    #include<cstdio>
    #include<cstring>
    #define maxn 40010
    using namespace std;
    int n,g[16][16],f[maxn][16],ans;
    int min(int x,int y){
        return x<y?x:y;
    }
    int main()
    {
        scanf("%d",&n);
        memset(f,127/3,sizeof(f));
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                scanf("%d",&g[i][j]);
        for(int k=0;k<=n;k++)
            for(int i=0;i<=n;i++)
                for(int j=0;j<=n;j++)
                    g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
        ans=f[0][0];f[0][0]=0;
        for(int i=1;i<(1<<n);i++)
            for(int j=1;j<=n;j++)if(i&(1<<j-1))
                for(int k=0;k<=n;k++)
                    f[i][j]=min(f[i][j],f[i-(1<<j-1)][k]+g[k][j]);
        for(int i=1;i<=n;i++)
            ans=min(ans,f[(1<<n)-1][i]+g[i][0]);
        printf("%d
    ",ans);
        return 0;
    }
    /*codevs 1358  状丫dp*/
    #include<cstdio>
    #include<cstring>
    #define maxn 1500
    using namespace std;
    int g[12][12],f[12][12][maxn],ans;
    int min(int x,int y){
        return x<y?x:y;
    }
    int main()
    {
        for(int i=1;i<=10;i++)
            for(int j=1;j<=10;j++)
                scanf("%d",&g[i][j]);
        memset(f,127/3,sizeof(f));
        f[1][1][1<<g[1][1]]=g[1][1];
        int mxx=1<<10,SS;
        for(int i=1;i<=10;i++)
            for(int j=1;j<=10;j++)
                for(int S=0;S<mxx;S++){
                    SS=S|(1<<g[i+1][j]);
                    f[i+1][j][SS]=min(f[i+1][j][SS],f[i][j][S]+g[i+1][j]);
                    SS=S|(1<<g[i][j+1]);
                    f[i][j+1][SS]=min(f[i][j+1][SS],f[i][j][S]+g[i][j+1]);
                }
        printf("%d
    ",f[10][10][mxx-1]);
        return 0; 
    } 
    /*codevs 2594 状丫 dp */
    #include<cstdio>
    #define inf 1e8
    #define maxn 2500
    using namespace std;
    int n,m,g[110][11],f[maxn];
    int min(int x,int y){
        return x<y?x:y;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&g[i][j]);
        for(int i=0;i<=(1<<n);i++)
            f[i]=inf;
        f[0]=0;
        for(int i=0;i<(1<<n);i++)
            for(int j=1;j<=m;j++){
                int S=i;
                for(int k=1;k<=n;k++){
                    if(g[j][k]==0)continue;
                    if(g[j][k]==1)S=S|(1<<k-1);
                    if(g[j][k]==-1&&S&(1<<k-1))
                        S-=(1<<k-1);
                }
                f[S]=min(f[S],f[i]+1);
            }
        if(f[(1<<n)-1]==inf)printf("The patient will be dead.
    ");
        else printf("%d
    ",f[(1<<n)-1]);
        return 0;
    }

    然后解决了历史遗留问题 现在看很简单吗似乎

    /*codevs 1339 背包dp + 最丑的高精2333*/
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int n,m,t,W[25],cnt,f[25][25][510],dp[510],money[110],ans1[210],ans2[210];
    char s[110];
    int init(){
        int x=0;char s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    int max(int x,int y){
        return x>y?x:y;
    }
    void mul1(int x){
        ans1[0]=money[0];
        for(int i=1;i<=ans1[0];i++)
            ans1[i]=money[i]*x;
        for(int i=1;i<=ans1[0];i++)
            if(ans1[i]>9){
                ans1[i+1]+=ans1[i]/10;ans1[i]%=10;
            }
        if(ans1[ans1[0]+1])ans1[0]++;
        while(ans1[ans1[0]]>9){
            ans1[ans1[0]+1]+=ans1[ans1[0]]/10;
            ans1[ans1[0]]%=10;ans1[0]++;
        }
        int k=1;
        for(int i=ans1[0];i>=1;i--)
            if(ans1[i]){
                k=i;break;
            }
        ans1[0]=k;
    }
    void mul2(int x){
        ans2[0]=money[0];
        for(int i=1;i<=ans2[0];i++)
            ans2[i]=money[i]*x;
        for(int i=1;i<=ans2[0];i++)
            if(ans2[i]>9){
                ans2[i+1]+=ans2[i]/10;ans2[i]%=10;
            }
        if(ans2[ans2[0]+1])ans2[0]++;
        while(ans2[ans2[0]]>9){
            ans2[ans2[0]+1]+=ans2[ans2[0]]/10;
            ans2[ans2[0]]%=10;ans2[0]++;
        }
        int k=1;
        for(int i=ans2[0];i>=1;i--)
            if(ans2[i]){
                k=i;break;
            }
        ans2[0]=k;
    }
    int main()
    {
        n=init();m=init();t=init();scanf("%s",s);
        int len=strlen(s);
        for(int i=len-1;i>=0;i--)
            if(s[i]>='0'&&s[i]<='9')
                money[++money[0]]=s[i]-'0';
        for(int i=1;i<=n;i++){
            scanf("%d",&W[i]);
            if(W[i]>t)cnt++;
        }
        for(int i=1;i<=m;i++)
            for(int l=1;l<=n;l++)
                for(int r=l;r<=n;r++){
                    for(int k=0;k<=t;k++)dp[k]=0;
                    for(int k=l;k<=r;k++)
                        for(int w=t;w>=W[k];w--)
                            dp[w]=max(dp[w],dp[w-W[k]]+1);
                    f[i][r][t]=max(f[i][r][t],f[i-1][l-1][t]+dp[t]);
                }
        mul1(f[m][n][t]);mul2(n-cnt-f[m][n][t]);
        for(int i=ans1[0];i>=1;i--)printf("%d",ans1[i]);printf(" ");
        for(int i=ans2[0];i>=1;i--)printf("%d",ans2[i]);
        return 0;
    }

    最大正方形子矩阵 开始还wa了QAQ

    /* codevs 1773 空间有点挤 猥琐的打short2333*/
    #include<iostream>
    #include<cstdio>
    #define maxn 2510
    using namespace std;
    short n,m,l[maxn][maxn],r[maxn][maxn],p[maxn][maxn],f[maxn][maxn],s[maxn][maxn],g[maxn][maxn],ans;
    short init(){
        short x=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    int main()
    {
        n=init();m=init();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                g[i][j]=init();
                if(g[i][j])f[i][j]=s[i][j]=1;
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(g[i-1][j]==0&&i>1)
                    p[i][j]=p[i-1][j]+1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(g[i][j-1]==0&&j>1)
                    l[i][j]=l[i][j-1]+1;
        for(int i=1;i<=n;i++)
            for(int j=m;j>=1;j--)
                if(g[i][j+1]==0&&j<m)
                    r[i][j]=r[i][j+1]+1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(g[i][j]&&g[i-1][j-1])//min min min  
                    f[i][j]=min(f[i-1][j-1],min(l[i][j],p[i][j]))+1;
                ans=max(ans,f[i][j]);
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(g[i][j]&&g[i-1][j+1])
                    s[i][j]=min(s[i-1][j+1],min(p[i][j],r[i][j]))+1;
                ans=max(ans,s[i][j]);
            }
        cout<<ans<<endl;
        return 0;
    }

    多维LIS问题

    /*codevs 1256 暴力n*n*m..... 20*/
    #include<cstdio>
    #define maxn 110
    using namespace std;
    int n,m,f[2][maxn][maxn],c[maxn],T,ans;
    short G[1010][maxn][maxn];
    int init(){
        int x=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    int max(int x,int y){
        return x>y?x:y;
    }
    int main()
    {
        freopen("mouse.in","r",stdin);
        freopen("mouse.out","w",stdout);
        n=init();m=init();
        int x,y,t;
        for(int i=1;i<=m;i++){
            t=init();x=init();y=init();
            G[t][x][y]++;T=max(T,t);
        }
        for(int i=1;i<=T;i++){
            for(int j=1;j<=n;j++)    
                for(int k=1;k<=n;k++){
                    f[i&1][j][k]=f[i-1&1][j][k];
                    if(j>1)f[i&1][j][k]=max(f[i&1][j][k],f[i-1&1][j-1][k]+G[i][j][k]);
                    if(k>1)f[i&1][j][k]=max(f[i&1][j][k],f[i-1&1][j][k-1]+G[i][j][k]);
                    if(j<n)f[i&1][j][k]=max(f[i&1][j][k],f[i-1&1][j+1][k]+G[i][j][k]);
                    if(k<n)f[i&1][j][k]=max(f[i&1][j][k],f[i-1&1][j][k+1]+G[i][j][k]);
                    ans=max(ans,f[i&1][j][k]);
                }
            for(int j=1;j<=n;j++)
                for(int k=1;k<=n;k++)
                    f[i-1&1][j][k]=0;
        }    
        printf("%d
    ",ans);
        return 0;
    } 
    /* codevs 1256 这有点打脸啊...多维LIS问题居然没看出来 还是太弱...*/
    #include<cstdio>
    #define maxn 10010
    using namespace std;
    int n,m,f[maxn],x[maxn],y[maxn],t[maxn],ans;
    int init(){
        int x=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    int max(int x,int y){
        return x>y?x:y;
    }
    int Abs(int x){
        return x>0?x:-x;
    }
    int main()
    {
        freopen("mouse.in","r",stdin);
        freopen("mouse.out","w",stdout);
        n=init();m=init();
        for(int i=1;i<=m;i++){
            t[i]=init();x[i]=init();y[i]=init();
        }
        for(int i=1;i<=m;i++){
            for(int j=1;j<i;j++)
                if(Abs(x[i]-x[j])+Abs(y[i]-y[j])<=t[i]-t[j])
                    f[i]=max(f[i],f[j]+1);
            ans=max(ans,f[i]);
        }    
        printf("%d
    ",ans+1);
        return 0;
    }

     单调队列优化dp

    /*codevs 3327 dp+单调队列优化 */
    #include<iostream>
    #include<cstdio>
    #define maxn 100010
    #define ll long long
    using namespace std;
    int n,k,q[maxn],head,tail;
    ll f[maxn],s[maxn],x,ans;
    ll init(){
        ll x=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='0')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x*f;
    }
    ll max(ll x,ll y){
        return x>y?x:y;
    }
    void Insert(int x){
        ll mx=f[x-1]-s[x];
        while(head<=tail&&f[q[tail]-1]-s[q[tail]]<mx)tail--;
        q[++tail]=x;
    }
    int main()
    {
        n=init();k=init();
        for(int i=1;i<=n;i++){
            x=init();s[i]=s[i-1]+x;
        }
        Insert(1);
        for(int i=1;i<=n;i++){
            if(i-q[head]>k)head++;
            f[i]=f[q[head]-1]-s[q[head]]+s[i];
            Insert(i+1);ans=max(ans,f[i]);
        }
        cout<<ans<<endl;
        return 0;
    }

     传说中的棋盘dp三水

    /*codevs 2853 n*n*n*n 卡过*/
    #include<cstdio>
    #define maxn 110
    using namespace std;
    int n,g[maxn][maxn],f[2][maxn][maxn][maxn];
    int Abs(int x){
        return x>0?x:-x;
    }
    int max(int x,int y){
        return x>y?x:y;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&g[i][j]);
        for(int x1=1;x1<=n;x1++){
            for(int y1=1;y1<=n;y1++)
                for(int x2=1;x2<=n;x2++)
                    for(int y2=1;y2<=n;y2++){
                        f[x1&1][y1][x2][y2]=max(f
    
    [x1&1][y1][x2][y2],f[x1-1&1][y1][x2-1][y2]+Abs(g[x1][y1]-g[x2][y2]));
                        f[x1&1][y1][x2][y2]=max(f
    
    [x1&1][y1][x2][y2],f[x1-1&1][y1][x2][y2-1]+Abs(g[x1][y1]-g[x2][y2]));
                        f[x1&1][y1][x2][y2]=max(f
    
    [x1&1][y1][x2][y2],f[x1&1][y1-1][x2-1][y2]+Abs(g[x1][y1]-g[x2][y2]));
                        f[x1&1][y1][x2][y2]=max(f
    
    [x1&1][y1][x2][y2],f[x1&1][y1-1][x2][y2-1]+Abs(g[x1][y1]-g[x2][y2]));
                    }
            for(int y1=1;y1<=n;y1++)
                for(int x2=1;x2<=n;x2++)
                    for(int y2=1;y2<=n;y2++)
                        f[x1-1&1][y1][x2][y2]=0;
        }
        printf("%d
    ",f[n&1][n][n][n]);
        return 0;        
    }
    /*codevs 2853 优化 f[i][j][k] Ax=i By=j k步 那么左边可以表示了就 Orz */
    #include<cstdio>
    #define maxn 210
    using namespace std;
    int n,g[maxn][maxn],f[maxn][maxn][maxn*2];
    int Abs(int x){
        return x>0?x:-x;
    }
    int max(int x,int y){
        return x>y?x:y;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&g[i][j]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                for(int k=1;k<=n*2-1;k++)if(k>j-1&&k>i-1){
                    f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k-1]+Abs(g[i][k-i+1]-g[k-j+1][j]));
                    f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]+Abs(g[i][k-i+1]-g[k-j+1][j]));
                    f[i][j][k]=max(f[i][j][k],f[i][j-1][k-1]+Abs(g[i][k-i+1]-g[k-j+1][j]));
                    f[i][j][k]=max(f[i][j][k],f[i][j][k-1]+Abs(g[i][k-i+1]-g[k-j+1][j]));
                }
        printf("%d
    ",f[n][n][2*n-1]);
        return 0;        
    }

    然后是线段覆盖类型 无聊打的nlogn优化

    /*codevs 3095 */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define maxn 1000010
    #define ll long long
    using namespace std;
    ll n,m,f[maxn],c[maxn],num,ans;
    struct node{
        ll l,r;
        ll v;
    }p[maxn];
    ll cmp(const node &x,const node &y){
        return (x.r==y.r&&x.l<y.l)||x.r<y.r;
    }
    ll init(){
        ll x=0;char s=getchar();
        while(s<'0'||s>'9')s=getchar();
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        return x;
    }
    int main()
    {
        m=init();
        for(int i=1;i<=m;i++){
            p[i].l=init();p[i].r=init();
            p[i].v=init();c[i]=p[i].r;
        }
        sort(p+1,p+1+m,cmp);sort(c+1,c+1+m);
        for(int i=1;i<=m;i++){
            ll pos=upper_bound(c+1,c+1+m,p[i].l)-c-1;
            f[i]=max(f[i-1],f[pos]+p[i].v);
            ans=max(ans,f[i]);
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    antd按需加载
    解决vscode开发react项目没有代码提示问题
    在react中配置less
    flutter之fluro导航传参数
    Flutter游戏:简单规则与结束页
    zsh: command not found:XXX
    React的安装与使用
    git stash 用法总结和注意点
    【OSS】工具类
    ajax将数组或list集合传到后台 的 【坑】
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5981808.html
Copyright © 2011-2022 走看看