题目链接:https://www.rqnoj.cn/problem/569
题意:
在一个数轴上可以摆M个线段,每个线段的起始终止端点给定(为整数),且每个线段有一个分值,问如何从中选取一些线段使得任意两个线段之间的距离大于等于R。每一条线段属于[0,N]。如何选择这些线段,使得分值之和最大?
定义:两线段间的距离 = 相邻端点坐标之差的绝对值
题解:
讲真。。。这里的N真的没用。。。
首先要用左端点从小到大排序。
表示状态:
dp[i] = max score (选了线段i的当前最大分值)
i:选了第i个线段
找出答案:
max dp[i]
如何转移:
枚举在i之前的线段j,判断位置是否合法。
if(lef[i]-rig[j]>=r) dp[i]=max(dp[i],dp[j]+val[i]);
边界条件:
dp[i] = val[i]
至少选上自己。
AC Code:
1 // state expression: 2 // dp[i] = max score 3 // i: ith segment is selected 4 // 5 // find the answer: 6 // max dp[i] 7 // 8 // transferring: 9 // if lef[i] - rig[j] >= r 10 // dp[i] = max dp[j] + w[i] 11 // 12 // boundary: 13 // dp[i] = w[i] 14 #include <iostream> 15 #include <stdio.h> 16 #include <string.h> 17 #include <algorithm> 18 #define MAX_M 1005 19 20 using namespace std; 21 22 struct Segment 23 { 24 int lef; 25 int rig; 26 int val; 27 Segment(int _lef,int _rig,int _val) 28 { 29 lef=_lef; 30 rig=_rig; 31 val=_val; 32 } 33 Segment(){} 34 friend bool operator < (const Segment &a,const Segment &b) 35 { 36 return a.lef<b.lef; 37 } 38 }; 39 40 int n,m,r; 41 int ans; 42 int dp[MAX_M]; 43 Segment s[MAX_M]; 44 45 void read() 46 { 47 cin>>n>>m>>r; 48 for(int i=0;i<m;i++) 49 { 50 cin>>s[i].lef>>s[i].rig>>s[i].val; 51 } 52 } 53 54 void solve() 55 { 56 sort(s,s+m); 57 for(int i=0;i<m;i++) 58 { 59 dp[i]=s[i].val; 60 for(int j=0;j<i;j++) 61 { 62 if(s[i].lef-s[j].rig>=r) 63 { 64 dp[i]=max(dp[i],dp[j]+s[i].val); 65 } 66 } 67 } 68 ans=0; 69 for(int i=0;i<m;i++) 70 { 71 ans=max(ans,dp[i]); 72 } 73 } 74 75 void print() 76 { 77 cout<<ans<<endl; 78 } 79 80 int main() 81 { 82 read(); 83 solve(); 84 print(); 85 }