• 动态规划2


    A - Max Sum Plus Plus[排列组合]

    这个真的很难搞,排列组合也太难了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 1e6+10;
    const int INF = 0x7fffffff;
    int a[maxn];
    int dp[maxn];
    int Max[maxn];//max(dp[i-1][k])就是上一组0~j-1的最大值
    int main(){
        int n,m,mmax;
        while(~scanf("%d%d",&m,&n))
        {
            for(int i = 1; i <= n; i++)
            {
                scanf("%d",&a[i]);
            }
            memset(dp,0,sizeof(dp));
            memset(Max,0,sizeof(Max));//分成0组的全是0
            for(int i = 1; i <= m; i++)
            {//分成i组
                mmax = -INF;
                for(int j = i; j <= n; j++)
                {//前j个数分成i组,至少需要i个数
                    dp[j] = max(dp[j-1]+a[j],Max[j-1]+a[j]);
                    //Max[j-1]目前代表的是分成i-1组前j-1个数的最大值,a[j]单独一组组成i组
                    //dp[j-1]代表j-1个数分成组,第j个数a[j]放在前面i组的一组中,两种方式选取较大者
                    Max[j-1] = mmax;//当前考虑的是j但是mmax是上一次循环得到的,所以更新的是j-1
                    mmax = max(mmax,dp[j]);//更新mmax,这样下次循环同样更新的是j-1
                }
                //这样也就更新得到了分i组的Max,下次分i+1组的时候就可以使用了
            }
            printf("%d
    ",mmax);
        }
        return 0;
    }

    B - Robot[概率]

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 1e6+10;
    int n,m,l,r,w;
    double dp[maxn],db[maxn];
    int main(){
    
        int n,m,mmax;
        while(~scanf("%d%d%d%d",&n,&m,&l,&r)&&(n||m||l||r))
        {
            db[0]=1;
            for(int i = 1; i <= m; i++)
            {
                scanf("%d",&w);
                for(int j=0;j<n;++j)
                {
                    if(db[j]>0)//剪枝
                    {
                        dp[(j+w+n)%n] += db[j]*0.5; //向前跳w步
                        dp[(j-w+n)%n] += db[j]*0.5; //向后跳w步
                    }
                }
    
                memcpy(db,dp,sizeof(double)*n);
                memset(dp,0,sizeof(double)*n);
            }
            double re=0;l--,r--;
            for(int i=l;i<=r;++i) re+=db[i];
            printf("%.4f
    ",re);
            memset(db,0,sizeof(dp));
            memset(db,0,sizeof(db));
        }
        return 0;
    }

    C - Happy Matt Friends[01背包+滚动数组]

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int MAX= 1<<20;
    int dp[2][MAX],a[44];
    int main()
    {
        int T,N,M;scanf("%d",&T);
        for(int t=1;t<=T;++t)
        {
            scanf("%d%d",&N,&M);
            memset(dp,0,sizeof(dp));
            dp[0][0]=1;
            for(int i = 1; i <= N; i++)
                scanf("%d",&a[i]);
                
            for(int i=1;i<=N;++i)
                for(int j=0;j<MAX;++j)
                    dp[i&1][j] = dp[(i-1)&1][j]+dp[(i-1)&1][j^a[i]];
                    
            long long re=0;
            int n=N&1;
            for(int i=M;i<MAX;++i)
            {
                re+=dp[n][i];
            }
            printf("Case #%d: %I64d
    ",t,re);
        }
        return 0;
    }

    D - 最大报销额[01背包]

    背包类型变成float型了,可以先放大后缩小来变成整形

    #include<iostream>
    #include<string.h>
    #include<map>
    #include<stdio.h>
    #define MAX 3000010
    using namespace std;
    int dp[MAX],bill[MAX];
    double q,temp[4];
    int N,ii,m;
    void Copy(double temp[])
    {
        int flag=1;double sum=0;
        for(int i=0;i<3;++i)
        {
            if(temp[i]>600){flag=0;break;}
            sum+=temp[i];
        }
        if(sum>1000)flag=0;
        if(flag)
        {
            bill[ii++]=(int)(sum*100);
        }
    }
    int main()
    {
        while(~scanf("%lf %d",&q,&N))
        {
            if(N==0) break;
            int Q=(int)(q*100);//double化整形
            memset(bill,0,sizeof(bill));ii=0;
    
            for(int nn=0;nn<N;++nn)//输入N个账单
            {
                scanf("%d",&m);getchar();
                memset(temp,0,sizeof(temp));int flag=1;
                for(int i=0;i<m;++i)//输入账单中的每个物品
                {
                    char t;double v;
                    scanf("%c:%lf",&t,&v);  getchar();
                    if('A'<=t&&t<='C'){ temp[t-'A']+=v;}
                    else { flag=0; }
                }
                if(flag)Copy(temp);//保存合法的账单
            }
            memset(dp,0,sizeof(dp));
            for(int i=0;i<ii;++i)
            {
                for(int j=Q;j>=bill[i];j--)
                {
                    dp[j]=max(dp[j],dp[j-bill[i]]+bill[i]);
                }
            }
            printf("%.2lf
    ",dp[Q]/100.0);
        }
        return 0;
    }

    E - FATE[二维完全背包]

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int MAX= 1<<20;
    int dp[101][101];
    struct a
    {
        int v,e;
    }a[101];
    int n,m,k,s;
    void f()
    {
        cout<<">>";
            for(int i=1;i<=m;++i)
            {
                cout<<dp[i]<<" ";
            }cout<<endl;
    }
    int main()
    {
        int j,i,t;
        while(~scanf("%d%d%d%d",&n,&m,&k,&s))
        {
    
            for(int y = 1; y <= k; y++)
                scanf("%d%d",&a[y].v,&a[y].e);
            memset(dp,0,sizeof(dp));
            for(i=1;i<=k;++i)
                for(j=a[i].e;j<=m;++j)
                    for(t=1;t<=s;++t)
                        if(dp[j][t]<(dp[j-a[i].e][t-1]+a[i].v))
                        {
                             dp[j][t] = dp[j-a[i].e][t-1]+a[i].v;
                        }
            if(dp[m][s]>=n)
            {
                for(int h=0;h<=m;++h)
                {
                    if(dp[h][s]>=n)
                    {
                        printf("%d
    ",m-h);break;
                    }
                }
            }
            else
                printf("-1
    ");
        }
        return 0;
    }
    

    F - Coins[多重背包+完全背包+01背包+二进制优化]

    #include <stdio.h>
     
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define MAX 1000000
    using namespace std;
    int dp[MAX];//存储最后背包最大能存多少
    int value[MAX],weight[MAX],number[MAX];//分别存的是物品的价值,每一个的重量以及数量
    int bag;
    void ZeroOnePack(int weight,int value )//01背包
    {
        int i;
        for(i = bag; i>=weight; i--)
        {
            dp[i] = max(dp[i],dp[i-weight]+value);
        }
    }
    void CompletePack(int weight,int value)//完全背包
    {
        int i;
        for(i = weight; i<=bag; i++)
        {
            dp[i] = max(dp[i],dp[i-weight]+value);
        }
    }
     
    void MultiplePack(int weight,int value,int number)//多重背包
    {
        if(bag<=number*weight)//如果总容量比这个物品的容量要小,那么这个物品可以直到取完,相当于完全背包
        {
            CompletePack(weight,value);
     
        }
        else//否则就将多重背包转化为01背包
        {
            int k = 1;
            while(k<=number)
            {
                ZeroOnePack(k*weight,k*value);
                number = number-k;
                k = 2*k;//这里采用二进制思想
            }
            ZeroOnePack(number*weight,number*value);
        }
    }
    int main()
    {
        int n;
        while(~scanf("%d%d",&n,&bag))
        {
            if(n==0&&bag==0)
                break;
            int i,sum=0;
            for(i = 0; i<n; i++)
                scanf("%d",&value[i]);//输入价值
            for(i=0;i<n;i++)
                scanf("%d",&number[i]);//输入数量  此题没有物品的重量,可以理解为体积和价值相等
            memset(dp,0,sizeof(dp));
            for(i = 0; i<n; i++)
            {
                MultiplePack(value[i],value[i],number[i]);//调用多重背包,注意穿参的时候分别是重量,价值和数量
            }
            int ans=0;
            for(i=1;i<=bag;i++)
            {
                if(i==dp[i])
                    ans++;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    G - Robberies[01背包]

    稍微要绕一下,被抓的概率要改成不被抓的概率,每偷一个不被抓的概率都会下降,要用乘法而不是加法

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int MAX= 1e4+3;
    double dp[MAX];
    struct
    {
        int m;
        double p;
    }bank[MAX];
    int N,T,S;
    double q,temp;
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
           scanf("%lf%d",&q,&N);S=0;q=1-q;
           for(int i=1;i<=N;++i)
           {
                scanf("%d%lf",&bank[i].m,&bank[i].p);
                bank[i].p=1-bank[i].p;//转化为不被抓的概率
                S+=bank[i].m;
           }
           memset(dp,0,sizeof(dp));dp[0]=1;
           for(int i=1;i<=N;++i)
                for(int j=S;j>=bank[i].m;--j)
                    dp[j]=max(dp[j],dp[j-bank[i].m]*bank[i].p);
           int re=0;
           for(int j=S;j>=0;--j)
           {
               if(!(dp[j]<q))
               {
                   printf("%d
    ",j);
                   break;
               }
           }
        }
        return 0;
    }
    

    H - Max Sum[01背包]

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int MAX= 1e5+5;
    int dp[MAX];
    int k[MAX];
    int N,T;
    int main()
    {
        scanf("%d",&T);
        int re=0,l,j,r;
        for(int tt=1;tt<=T;++tt)
        {
           scanf("%d",&N);
           for(int i=1;i<=N;++i) scanf("%d",&k[i]);
           memset(dp,0,sizeof(dp));
           l=r=j=1,re=k[1];dp[1]=k[1];
           for(int i=2;i<=N;i++)
    		{
    			if(dp[i-1]+k[i]>=k[i])
    			{
    				dp[i]=dp[i-1]+k[i];
    			}
    			else
    			{
    				dp[i]=k[i];
    				j=i;
    			}
    			if(dp[i]>re)
    			{
    				re=dp[i];
    				l=j;
    				r=i;
    			}
    		}
    		printf("Case %d:
    %d %d %d
    ",tt,re,l,r);
    		if(tt!=T)
                printf("
    ");
        }
        return 0;
    }
    

    I - Super Jumping! Jumping! Jumping![010背包]

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int MAX = 1002;
    int k[MAX],dp[MAX];
    int N,T;
    int main()
    {
        while(~scanf("%d",&T)&&T)
        {
            memset(k,0,sizeof(k));
            for(int i=1;i<=T;++i) scanf("%d",&k[i]);
            for(int i=1;i<=T;++i)
            {
                int big=0;
                for(int j=1;j<i;++j)
                  if(k[j]<k[i])
                       big=max(big,dp[j]);
                dp[i]=big+k[i];
            }
            int ans=-1;
            for(int i=1;i<=T;++i)
                ans=max(ans,dp[i]);
            cout<<ans<<endl;
        }
        return 0;
    }
    

    J - Calling Extraterrestrial Intelligence Again[完全不知道哪里跟dp有关]

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int MAX = 1e5+5;
    int k[MAX],dp[MAX];
    int N,T;
    int prim[MAX] = {1}, s[MAX],l=0;
    int m,a,b,p,q;
    void prime()
    {
    	int i, j;
    	memset(prim, 0, sizeof(prim));
    	for (i = 2; i < MAX; i++)
    	{
    		if (prim[i])continue;
    		for (j = i + i; j < MAX; j += i)
    		{
    			prim[j] = 1;
    		}
    		s[l++] = i;
    	}
    	//s里面保存的是2-MAX的素数
    }
    bool Check_p(int x,int y)
    {
        return (prim[x]==0)&&(prim[y]==0);
    }
    bool Check_f(int x,int y)
    {
        return a*y>x*b;
    }
    struct V
    {
        int pp,qq,mm;
    }big;
    int main()
    {
        prime();
        while(~scanf("%d%d%d",&m,&a,&b)&&(m||a||b))
        {
           int End=(int)sqrt(m);
           big.mm=big.pp=big.qq=0;
           for(int i=0;s[i]<=End;++i)
           {
              p=s[i];q=m/s[i];
              while(prim[q]||Check_f(p,q)) q--;
             // printf("%d %d %d
    ",p,q,s[i]);
              if(big.mm<p*q)
              {
                  big.mm=p*q;
                  big.pp=p;
                  big.qq=q;
              }
            }
            printf("%d %d
    ",big.pp,big.qq);
        }
        return 0;
    }
    

      

  • 相关阅读:
    【H3 BPM工作流程管理产品小故事】第六篇 条件可见与条件必填
    【H3 BPM工作流程管理产品小故事】第五篇 必填与水印文本
    【H3 BPM工作流程管理产品小故事】第四篇 子表创建
    【工作流程管理产品小故事】第三篇 参与者与数据加载
    【H3 BPM工作流程管理产品小故事】第二篇 文本默认值
    【H3 BPM工作流程管理产品小故事】第一篇 配置简单流程
    流程管理产品小故事汇总贴
    【H3 BPM工作流程产品小故事】第十四篇 数据字典与数据联动
    【H3 BPM工作流程产品小故事】第十三篇 消息通知
    【H3 BPM工作流程产品小故事】第十二篇 触发其他流程
  • 原文地址:https://www.cnblogs.com/chrysanthemum/p/12449082.html
Copyright © 2020-2023  润新知