这题就是一个最基本的0-1背包。刚学DP的人(比如说我)拿来上手应该是很不错的。题意就不多说了,应该都是很熟悉的了。我是看了《背包九讲》后做的,感觉上面说的很好!

 

一:下面这个程序是最基本的,就是没有什么优化的。

状态转移方程:Div[i][v]=max(Div[i-1][v],Div[i-1][v-w[i]]+c[i]);  

#include <iostream>
using namespace std;
#define MAX 1002

int Div[MAX][MAX];
int c[MAX];      //价值
int w[MAX];      //体积

int max(int a,int b)
{
    if(a>b)
        return a;
    return b;
}

int main()
{
    int t,n,v,i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&v);
        memset(Div,0,sizeof(Div));
        for(i=1;i<=n;i++)
            scanf("%d",&c[i]);
        for(i=1;i<=n;i++)
            scanf("%d",&w[i]);

        for(i=1;i<=n;i++)
        {
            for(j=0;j<=v;j++)
            {
                if(j>=w[i])
                    Div[i][j]=max(Div[i-1][j],Div[i-1][j-w[i]]+c[i]);
                else
                    Div[i][j]=Div[i-1][j];
            }
        }

        cout<<Div[n][v]<<endl;
    }
    return  0;
}


二:由于时间复杂度已经不能再进行大的优化了。但发现空间使用是很大的,可以在空间上进行优化,既把记录数组Div由二维变成一维,这是可以的。这就是动态数组的思想,因为前面的数组用过之后,就可以用后面的数组去回滚掉!

动态转移方程:Div[v]=max(Div[v],Div[v-w[i]]+c[i]);

 

#include <iostream>
using namespace std;
#define MAX 1002

int Div[MAX];
int c[MAX];      //价值
int w[MAX];      //体积

int max(int a,int b)
{
    if(a>b)
        return a;
    return b;
}

int main()
{
    int t,n,v,i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&v);
        memset(Div,0,sizeof(Div));

        for(i=1;i<=n;i++)
            scanf("%d",&c[i]);
        for(i=1;i<=n;i++)
            scanf("%d",&w[i]);

        for(i=1;i<=n;i++)
        {
            for(j=v;j>=w[i];j--)
            {
                Div[j]=max(Div[j],Div[j-w[i]]+c[i]);
            }
        }

        cout<<Div[v]<<endl;
    }
    return  0;
}

 

三:后来,改了一小下,更好看了一下,但无大用:

#include <iostream>
using namespace std;
#define MAX 1002

int Div[MAX];
int c[MAX];      //价值
int w[MAX];      //体积

int main()
{
    int t,n,v,i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&v);
        memset(Div,0,sizeof(Div));

        for(i=1;i<=n;i++)
            scanf("%d",&c[i]);
        for(i=1;i<=n;i++)
            scanf("%d",&w[i]);

        for(i=1;i<=n;i++)
        {
            for(j=v;j>=w[i];j--)
            {
                if(Div[j-w[i]]+c[i]>Div[j])
                    Div[j]=Div[j-w[i]]+c[i];
            }
        }

        cout<<Div[v]<<endl;
    }
    return  0;
}

上面的三个程序自我感觉很是可以的,应该没有更好的方法了。希望借此入门,能对DP有些许点了解!