原題連結
題解
1.當沒有花費限制的時候,我們可以將其抽象為簡單的揹包問題
2.如果有了花費限制,那麼我們就再加一維條件
3.如果一個線段能用,那麼它前面一定是鋪滿的,那我們令線段按起點排序,透過某種運算,保證放這個線段時,前面的線段組成是最優的
比如在 \(i\) 點結尾位置花費 \(j\) 所達到的最優值,這個最優值與後面線段怎麼擺無關,所以可以存起來減少重複運算,這也是dp的核心
code
#include<bits/stdc++.h>
using namespace std;
struct node
{
int start,len,v,c;
}seg[10005];
bool cmp(node a,node b)
{
if(a.start!=b.start) return a.start<b.start;
return a.len<b.len;
}
int f[1005][1005]={0};
int main()
{
int l,n,b;
cin>>l>>n>>b;
for(int i=1;i<=n;i++)
{
cin>>seg[i].start>>seg[i].len>>seg[i].v>>seg[i].c;
}
sort(seg+1,seg+1+n,cmp);
for(int i=0;i<=l;i++)
{
for(int j=1;j<=n;j++)
{
int start=seg[j].start;
if(start==i)
{
int ends=start+seg[j].len;
if(i==0) f[ends][seg[j].c]=max(seg[j].v,f[ends][seg[j].c]);
for(int k=seg[j].c;k<=b;k++) if(f[start][k-seg[j].c]) f[ends][k]=max(f[start][k-seg[j].c]+seg[j].v,f[ends][k]);
}
}
}
int ans=0;
for(int i=1;i<=b;i++) ans=max(ans,f[l][i]);
cout<<(ans?ans:-1);
return 0;
}