题目链接
题目大意:
总共要升两级,有n个任务,每个任务有在第一级时候所获得的经验值和所需的时间,每个任务也有在第二级的时候所获得的经验值和所需的时间。其中第一级升级之后多余的经验放入第二级。问升两级所需要的最少时间是多少?如果不能就输出-1。
解题思路:
定义dp[i][j]为获得第一级经验为i,第二级经验为j所需要的最少时间,可以考虑使用01背包逆序求解以减少第几个任务的这个维度。
重点:需要对第一级的经验进行升序排序后,否则顺序会影响dp结果。如果第一级经验分别为:90,40,40,且第一级所需要的经验为100,则溢出情况只有130这种情况,但是40,40,90就有40+90=130,40+40+90=170两种情况,所以要进行升序排序,不然会有情况遗漏。
解题代码:
#include<bits/stdc++.h>
using namespace std;
mt19937 rng_32(chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
const ll maxn=2e5+10;
ll inf=1e18;
ll dp[1010][1010];
struct E{
int x,t,y,r;
}p[505];
bool cmp(E a1,E a2)
{
return a1.x<a2.x;
}
int main()
{
ll n,s1,s2;
cin>>n>>s1>>s2;
for (ll i=0;i<=1000;i++)
{
for (ll j=0;j<=1000;j++)
dp[i][j]=inf;
}
dp[0][0]=0;
for (ll i=1;i<=n;i++)
{
cin>>p[i].x>>p[i].t>>p[i].y>>p[i].r;
}
sort(p+1,p+1+n,cmp);
for (ll i=1;i<=n;i++)
{
for (ll j=1000;j>=0;j--)
{
for (ll k=1000;k>=0;k--)
{
ll t1=inf,t2=inf;
if (j>=p[i].x && j-p[i].x<s1)
t1=dp[j-p[i].x][k]+p[i].t;
if (k>=p[i].y)
t2=dp[j][k-p[i].y]+p[i].r;
dp[j][k]=min(dp[j][k],min(t1,t2));
}
}
}
ll ans=inf;
for (ll j=s1;j<=1000;j++)
{
for (ll k=max(0ll,s2-(j-s1));k<=1000;k++)
{
ans=min(ans,dp[j][k]);
}
}
if (ans==inf)
ans=-1;
cout<<ans;
return 0;
}