题目关键在于,对于时间最少的方法,一定按照题目最早可以开始做的时间的顺序做,即按照l-t的从小到大顺序来做。
不妨假设1的开始时间小于2,那么一旦先做2,很明显从做完上件题目后的等待时间加长,因此可以得出最优解一定按照l-t的顺序做。
然后就是两种方法了,一种背包,一种二分,背包是求出了每个时间的最优值,而二分加dfs只是不断验证是否可行再二分的过程,事实证明,后者省去很多时间。
附代码:
背包:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <vector>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define delf int m=(l+r)>>1
#define ll long long int
using namespace std;
int n,w;
int ans;
ll dp[3000010];
struct node
{
int t,v,l;
} a[33];
bool cmp(node a1,node b1)
{
if (a1.l-a1.t!=b1.l-b1.t)
return a1.l-a1.t<b1.l-b1.t;
return a1.l<b1.l;
}
ll max(ll a,ll b)
{
return a>b?a:b;
}
int main()
{
while (~scanf("%d%d",&n,&w))
{
memset(dp,0,sizeof(dp));
int s1=0;
int s2=0;
int l=0;
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].t,&a[i].v,&a[i].l);
s1+=a[i].v;
s2+=a[i].t;
l=max(l,a[i].l);
}
if (s1<w)
{
printf("zhx is naive!\n");
continue ;
}
s2+=l;
sort(a+1,a+n+1,cmp);
int ans=s2;
for (int i=1;i<=n;i++)
{
for (int t=s2;t>=a[i].l&&t>=a[i].t;t--)
{
dp[t]=max(dp[t],dp[t-a[i].t]+a[i].v);
if (dp[t]>=w&&t<ans)
ans=t;
}
}
printf("%d\n",ans);
}
return 0;
}
二分:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <vector>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define delf int m=(l+r)>>1
#define ll long long int
using namespace std;
int n,w;
int ans;
int sum[31];
struct node
{
int t,v,l;
} a[31];
bool cmp(node a1,node b1)
{
return a1.l-a1.t<b1.l-b1.t;
}
void dfs(int s,int t,int p)
{
if (ans==1)
return ;
if (p>=w)
{
ans=1;
return ;
}
if (s<=0||t<1)
return ;
if (p+sum[t]<w)
return ;
if (s>=a[t].l&&s>=a[t].t)
dfs(s-a[t].t,t-1,p+a[t].v);
dfs(s,t-1,p);
return ;
}
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
while (~scanf("%d%d",&n,&w))
{
memset(sum,0,sizeof(sum));
int s1=0;
int s2=0;
int p=0;
for (int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].t,&a[i].v,&a[i].l);
s1+=a[i].v;
s2+=a[i].t;
p=max(p,a[i].l);
}
sort(a+1,a+n+1,cmp);
s2+=p;
sum[0]=0;
for (int i=1;i<=n;i++)
{
sum[i]=sum[i-1]+a[i].v;
}
if (s1<w)
{
printf("zhx is naive!\n");
continue ;
}
int l=1;
int h=s2;
while (l<=h)
{
int m=(l+h)>>1;
ans=0;
dfs(m,n,0);
if (ans==1)
h=m-1;
else
l=m+1;
}
printf("%d\n",l);
}
}