刚开始做,想到的方法是,按照时间顺序,从小到大,排完序之后,在节点i处的最大值一定在满足条件的节点j后。
满足的条件是:第j个节点结束时间小于i节点的开始时间。
那么j可以为1<=j<i;
即 dp[i]=max(dp[i],dp[j])+c[i] (1<=j<i)
#include <iostream>
#include<algorithm>
using namespace std;
struct work
{
long s,e,c;
}w[1005];
int cmp(work w1,work w2)
{
if(w1.s==w2.s&&w1.e==w2.e)
return w1.c>=w2.c;
if(w1.s==w2.s)
return w1.e<w2.e;
return w1.s<w2.s;
}
int main()
{
// freopen("in.txt","r",stdin);
int t;
int m,n;
int dp[1005];
int k=0;
long a,b,c;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&m,&n);
k=1;
for(int i=1;i<=n;i++)
{
scanf("%ld %ld %ld",&a,&b,&c);
if(a>=1&&b<=m)
{ w[k].s=a; w[k].e=b; w[k].c=c; k++; }
}
sort(w+1,w+k,cmp);
for(int i=1;i<k;i++)
dp[i]=0;
if(w[1].s<=m&&w[1].e<=m)
dp[1]=w[1].c;
for(int i=2;i<k;i++)
{
for(int j=1;j<i;j++) //从1开始到i-1遍历,只要w[j].e<w[i].s,说明i可以跟在j的后面
if(w[j].e<w[i].s&&dp[j]>dp[i]) //找到最大值
dp[i]=dp[j];
dp[i]+=w[i].c; //加上本身的值
}
long max_c=0;
for(int i=1;i<k;i++) //所有的节点搜完最大值之后,最大值并不一定在dp[k-1]中
if(dp[i]>max_c)
max_c=dp[i];
printf("%ld\n",max_c);
}
return 0;
}
后来,看了下discuss。看到了01背包的做法。
dp[i][j]=max(dp[i-1][j],dp[i][s[i]-1]+c[i]) j>=e[i];
#include <iostream>
#include<algorithm>
using namespace std;
struct work
{
long s,e,c;
}w[1005];
int cmp(work w1,work w2)
{
if(w1.s==w2.s&&w1.e==w2.e)
return w1.c>=w2.c;
if(w1.s==w2.s)
return w1.e<w2.e;
return w1.s<w2.s;
}
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
// freopen("in.txt","r",stdin);
int t;
int m,n;
int dp[110];
int k=0;
long a,b,c;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&m,&n);
k=1;
for(int i=1;i<=n;i++)
{
scanf("%ld %ld %ld",&a,&b,&c);
if(a>=1&&b<=m)
{ w[k].s=a; w[k].e=b; w[k].c=c; k++; }
}
sort(w+1,w+k,cmp);
for(int i=0;i<=m;i++)
dp[i]=0;
for(int i=1;i<k;i++)
for(int j=m;j>=w[i].e;j--)
dp[j]=max(dp[j],dp[w[i].s-1]+w[i].c);
printf("%d\n",dp[m]);
}
return 0;
}