大致题意:有一个人做事情,每件事情价值v,耗时t,在规定的时间内做总价值和最大的事情,求最大价值
测试案例:
input:
3 70(n,T) 71 100(ti,vi) 69 1 1 2
output:
3
解题思路:这题看上去是0-1背包,但是时间t太大,0-1背包不好开这么大的数组,所以用搜索写,这里开2个后缀数组,分别是到当前位置i时i-n的时间总和与到当前位置i时i-n的价值总和,用于剪枝,即当前搜索到的位置所用时间+后缀时间>T即剪枝以及当前搜索到的位置所得到价值+后缀价值<=sum即剪枝,另外时间按从大到小排序,从小到大排序会超时..
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn=110;
struct node
{
ll t,v;
bool operator<(const node &nd)const
{
return t>nd.t;
}
};
node nd[maxn];
int n,cnt;
ll sum,T;
ll rv[maxn],rt[maxn];
void dfs(int i,ll uv,ll ut)
{
sum=max(uv,sum);
if (i==n)
{
return;
}
if (sum>=uv+rv[i])
return;
if (T>=ut+rt[i])
{
sum=max(uv+rv[i],sum);
return;
}
if (ut+nd[i].t<=T)
{
dfs(i+1,uv+nd[i].v,ut+nd[i].t);
}
dfs(i+1,uv,ut);
}
int main()
{
int i;
while (scanf("%I64d%I64d",&n,&T)==2)
{
cnt=0;
for (i=0; i<n; i++)
{
scanf("%I64d%I64d",&nd[cnt].t,&nd[cnt].v);
if (nd[cnt].t<=T)
{
cnt++;
}
}
n=cnt;
sort(nd,nd+n);
rv[n]=rt[n]=0;
for (i=n-1; i>=0; i--)
{
rv[i]=rv[i+1]+nd[i].v;
rt[i]=rt[i+1]+nd[i].t;
}
sum=0;
dfs(0,0,0);
printf("%I64d\n",sum);
}
}