ZOJ 3703 Happy Programming Contest 01背包+记录路径

In Zhejiang University Programming Contest, a team is called "couple team" if it consists of only two students loving each other. In the contest, the team will get a lovely balloon with unique color for each problem they solved. Since the girl would prefer pink balloon rather than black balloon, each color is assigned a value to measure its attractiveness. Usually, the boy is good at programming while the girl is charming. The boy wishes to solve problems as many as possible. However, the girl cares more about the lovely balloons. Of course, the boy's primary goal is to make the girl happy rather than win a prize in the contest.

Suppose for each problem, the boy already knows how much time he needs to solve it. Please help him make a plan to solve these problems in strategic order so that he can maximize the total attractiveness value of balloons they get before the contest ends. Under this condition, he wants to solve problems as many as possible. If there are many ways to achieve this goal, he needs to minimize the total penalty time. The penalty time of a problem is equal to the submission time of the correct solution. We assume that the boy is so clever that he always submit the correct solution.

Input

The first line of input is an integer N (N < 50) indicating the number of test cases. For each case, first there is a line containing 2 integers T (T <= 1000) and n (n <= 50) indicating the contest length and the number of problems. The next line contains n integers and the i-th integer ti (ti <= 1000) represents the time needed to solve the ith problem. Finally, there is another line containing n integers and the i-th integer vi (vi <= 1000) represents the attractiveness value of the i-th problem. Time is measured in minutes.

Output

For each case, output a single line containing 3 integers in this order: the total attractiveness value, the number of problems solved, the total penalty time. The 3 integers should be separated by a space.

Sample Input
2
300 10
10 10 10 10 10 10 10 10 10 10
1 2 3 4 5 6 7 8 9 10
300 10
301 301 301 301 301 301 301 301 301 301
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000

Sample Output
55 10 550
0 0 0


    题意是说限制时间,问在这个限制的时间内最多获得的最大吸引力是多少,并输出做了几道题,而且总罚时为多少(罚时的计算方法为做所有题的当前时间的总和),分离开来看,其实就是一个01背包的问题,然后为了让罚时最少,则将得出的结果进行一下排序再计算输出罚时就可以了。

    和普通的01背包不同的一点是这道题要进行路径的记录。对于路径的记录则是要另开一个数组进行记录,如果在dp过程中路径发生了改变,则进行一次记录,最后在查找的时候再进行一遍回溯就可以了。

    下面AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t[1005];
int v[1005];
int f[1005];
int p[1005][1005];
int q[1005];

int main()
{
    int n,m;
    int i,j;
    int T;
    int k;
    scanf("%d",&T);
    while(T--)
    {
        k=0;
        memset(t,0,sizeof(t));
        memset(v,0,sizeof(v));
        memset(f,0,sizeof(f));
        memset(p,0,sizeof(p));
        memset(q,0,sizeof(q));
        scanf("%d%d",&n,&m);
        for(i=1;i<=m;i++)
        {
            scanf("%d",&t[i]);
        }
        for(i=1;i<=m;i++)
        {
            scanf("%d",&v[i]);
        }
        for(i=1;i<=m;i++)
        {
            for(j=n;j>=1;j--)
            {
                if(t[i]<=j)
                {
                    if(f[j]>=f[j-t[i]]+v[i])
                        f[j]=f[j];
                    else
                    {
                        f[j]=f[j-t[i]]+v[i];
                        p[i][j]=1;
                    }
                }
            }
        }
        for(i=m,j=n;i>0;i--)
        {
            if(p[i][j]==1)
            {
                q[k]=t[i];
                k++;
                j-=t[i];
            }
        }
        sort(q,q+k);
        int ans;
        ans=q[0];
        for(i=1;i<k;i++)
        {
            q[i]=q[i]+q[i-1];
            ans+=q[i];
        }
        cout<<f[n]<<" "<<k<<" "<<ans<<endl;
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值