RQNOJ 569 Milking Time:dp & 线段问题

题目链接: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 }
原文地址:https://www.cnblogs.com/Leohh/p/7461343.html