• SPOJ 181


    潜水员要潜水,给出n个气缸(1<=n<=1000),每个气缸中有氧气量为ti,氮气量为ai,气缸重量为wi(1<=ti<=21,1<=ai<=79,1<=wi<=800)。现在潜水员需要量为t的氧气,量为a的氮气(1<=t<=21,1<=a<=79),问选哪些气缸,使得重量最小。

    【背包】二维背包问题,不同的是这个要选的物品占两种容量至少为t和a。

    设dp[i][j][k]为氧气量为j,氮气量为k时的最小重量

    dp[i][j][k]=min{ dp [ i-1 ] [ j-t[i] ] [ k-a[i] ] + w[i] }

    显然第一维可以在用循环覆盖省略掉

    一开始我这样是这样写的

    for (i=1;i<=m;i++)
    {
        for (j=ti;j>=0;j--)
            {
            for (k=ai;k>=0;k--)
            {
                if (dp[j+t[i]][k+a[i]]>dp[j][k]+w[i])
                {
                    dp[j+t[i]][k+a[i]]=dp[j][k]+w[i];
                    if (j+t[i]>=ti && k+a[i]>=ai) ans=min(ans,dp[j+t[i]][k+a[i]]);
                }
            }
        }
    }

    然后就WA了,一开始怎么也找不到错误,后来发现是循环边界有问题,假如数据

    1 5
    3
    1 1 3
    1 2 4
    1 2 5

    显然答案是三个全部都用上,

    当扫描到第三个物品时,j必须是2,才能假如该物品,但是代码中j不可能取到2,这里发生了错误。

    更好的办法就是当j+t[i]>ti时一律将j+t[i]视为ti,k+a[i]视为ai。

    for (i=1;i<=m;i++)
    {
        for (j=ti;j>=0;j--)
        {
            for (k=ai;k>=0;k--)
            {
                x=j+t[i];if (x>ti) x=ti;
                y=k+a[i];if (y>ai) y=ai;
                if (dp[x][y]>dp[j][k]+w[i])
                {
                    dp[x][y]=dp[j][k]+w[i];
                }
            }
        }
    }

    完整代码:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<string>
    #include<sstream>
    #define eps 1e-9
    #define ALL(x) x.begin(),x.end()
    #define INS(x) inserter(x,x.begin())
    #define FOR(i,j,k) for(int i=j;i<=k;i++)
    #define MAXN 1005
    #define MAXM 40005
    #define INF 0x3fffffff
    using namespace std;
    typedef long long LL;
    int i,j,k,n,m,x,y,T,ans,big,cas,num,len;
    bool flag;
    
    int ti,ai,t[1005],a[1005],w[1005],dp[1005][1005];
    
    int main()
    {
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d%d",&ti,&ai);
            scanf("%d",&m);
            for (i=1;i<=m;i++)
            {
                scanf("%d%d%d",&t[i],&a[i],&w[i]);
            }
            
            memset(dp,0x2f,sizeof(dp));
            dp[0][0]=0;
            
            ans=INF;
            
            for (i=1;i<=m;i++)
            {
                for (j=ti;j>=0;j--)
                {
                    for (k=ai;k>=0;k--)
                    {
                        x=j+t[i];
                        y=k+a[i];
                        if (x>ti) x=ti;
                        if (y>ai) y=ai;
                        if (dp[x][y]>dp[j][k]+w[i])
                        {
                            dp[x][y]=dp[j][k]+w[i];
                        }
                    }
                }
            }
            printf("%d
    ",dp[ti][ai]);
        }
        return 0;
    }
  • 相关阅读:
    第五周学习进度
    第四周学习进度
    四则运算三
    第三周学习进度
    软件工程个人作业—四则运算2
    软件工程个人作业01
    软件工程概论—用户登录界面
    构建之法读书笔记06
    构建之法读书笔记05
    构建之法读书笔记04
  • 原文地址:https://www.cnblogs.com/zhyfzy/p/4285504.html
Copyright © 2020-2023  润新知