E - Coin Change UVA - 674 &&(一些记录路径的方法)

这一道题并不难,我们只需要将dp数组先清空,再给dp【0】=1,之后就按照完全背包的模板写

主要是我们要证明着一种方法不会出现把(1+3+4)(1+4+3)当作两种方法,这一点如果自己写过背包的那个表的话肯定知道是不会出先这种情况的

证明如下:(就拿这一道题的第一个例子来举例)

             0  1  2  3  4  5  6  7  8  9  10  11  12

d=1      1  1  1  1   1  1  1  1  1  1    1   1    1

d=5       1  1  1  1  1  2  2  2  2  2   3   3   3

d=10     1  1  1  1  1  2  2  2  2  2   4  4   4

由此可见是不会出现把(5  5  1)(1  5  5)当两种情况,,因为按顺序来是先让1来填冲数组,所以每一个数中如果有一,那肯定是最先加进去的,不可能在之后又加进去,而且相同的数要是出现多次肯定是在一起出现的,不会出现(5 1 5)这种情况。。。。好了,到这里我算结束了。。。。

代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 int q[10],v[8000];
 4 int main()
 5 {
 6     int a,s,d,f,g;
 7     q[1]=1;
 8     q[2]=5;
 9     q[3]=10;
10     q[4]=50;
11     q[5]=25;
12     while(~scanf("%d",&a))
13     {
14         memset(v,0,sizeof(v));
15         v[0]=1;
16         for(s=1; s<=5; ++s)
17         {
18             for(d=0; d+q[s]<=a; ++d)
19             {
20                 v[d+q[s]]=v[d]+v[d+q[s]];
21             }
22         }
23         printf("%d\n",v[a]);
24     }
25     return 0;
26 }

下面是01背包等的一些模板加上记录路径      转自:https://blog.csdn.net/m0_37830950/article/details/70243226

01模板:

#include <iostream>
#include<algorithm>

using namespace std;

int main()
{
    int total_weight = 10;
    int w[6] = { 0,5,4,3,2,1 };
    int v[6] = { 0,1,2,3,4,5 };
    int dp[11] = { 0 };
    int path[6][11] = { 0 };

    for (int i = 1; i <= 5; i++)
        for (int j = 10; j >= w[i]; j--)
            if (dp[j] < dp[j - w[i]] + v[i])
            {
                dp[j] = dp[j - w[i]] + v[i];
                path[i][j] = 1;
            }

    int i = 5, j = 10;
    while (i > 0 && j > 0)
    {
        if (path[i][j] == 1)
        {
            cout << i << ' ';
            j -= w[i];
        }
        i--;
    }
    cout << endl;

    cout << "总的价值为: " << dp[10] << endl;
    return 0;
}

另外一种二维数组的:

#include<bits/stdc++.h>
#define MAXN 0x7ff
using namespace std;
int m,n,w[MAXN],c[MAXN];
int f[MAXN][MAXN],i,j;//f[i][v]表示第i件物品放入容量为v的背包所能产生的最大价值。 
int maxn(int x,int y)//比较,输出最大值 
{
    if(x>y)
    return x;
    else 
    return y;
}
int main()
{
    cin>>m>>n;    
    for(i=1;i<=n;i++)
        cin>>w[i]>>c[i];//输入不解释 
    for(i=1;i<=n;i++)
        for(j=m;j>0;j--)
        {
            if(w[i]<=j)
            f[i][j]=maxn(f[i-1][j],f[i-1][j-w[i]]+c[i]);//状态转移方程式。 
            else f[i][j]=f[i-1][j];
        }
        cout<<f[n][m];
        return 0;
}

完全背包

#include <iostream>
#include<algorithm>

using namespace std;

int main()
{
    int total_weight = 10;
    int w[6] = { 0,5,4,3,2,1 };
    int v[6] = { 0,1,2,3,4,5 };
    int dp[11] = { 0 };
    int path[6][11] = { 0 };

    for (int i = 1; i <= 5; i++)
        for (int j = w[i]; j <= 10; j++)
            if (dp[j] < dp[j - w[i]] + v[i])
                {
                    dp[j] = dp[j - w[i]] + v[i];
                    path[i][j]=1;
                }

    int i = 5, j = 10;
    while (i > 0 && j > 0)
    {
        if (path[i][j] == 1)
        {
            cout << i << ' ';
            j -= w[i];
        }
        else
            i--;
    }
    cout << endl;

    cout << "总的价值为: " << dp[10] << endl;
    return 0;
}

多重背包

#include <iostream>
#include<algorithm>

using namespace std;

int main()
{
    int total_weight = 10;
    int w[6] = { 0,5,4,3,2,1 };
    int v[6] = { 0,1,2,3,4,5 };
    int cot[6] = { 0,1,2,1,2,1 };
    int dp[11] = { 0 };
    int path[6][11] = { 0 };

    for (int i = 1; i <= 5; i++)
        for (int k = 1; k <= cot[i]; k++)
            for (int j = 10; j >= w[i]; j--)
                if (dp[j] < dp[j - w[i]] + v[i])
                {
                    dp[j] = dp[j - w[i]] + v[i];
                    path[i][j] = 1;
                }

    int i = 5, j = 10;
    while (i > 0 && j > 0)
    {
        if (path[i][j] == 1&&cot[i])
        {
            cout << i << ' ';
            j -= w[i];
            cot[i]--;
        }
        else
            i--;
    }
    cout << endl;

    cout << "总的价值为: " << dp[10] << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/kongbursi-2292702937/p/10693253.html