UCF Local Programming Contest Round 1A - solution to question F (option dp of activities with rights)
Title Link: Trading Cards
There are two inputs in the first line. T and p respectively mean that there are t exams and p students.
Enter the following t lines. Each line inputs three attributes of an exam, s, e and a, respectively indicating that the exam starts at s and ends at e. the full score of this exam is a.
Next, there are p groups of input, each group has t lines, and the j line in group i represents the percentage of the score that the i student can obtain in the j test in the total score.
Finally, you need to output the serial numbers and grades of the three students with the best grades
The data range given by the title is
(1 ≤ t ≤ 10000)
(3 ≤ p ≤ 100)
(0 ≤ s < e ≤ 10000)
(1 ≤ a ≤ 100)
After reading the topic, we found that for each student, their grades do not interfere with each other, so we just need to discuss how to calculate the highest score for a student.
At this time, my first reaction is a knapsack like problem. I can choose or not for each exam. So I built a two-dimensional array DP [i] [J], where I represents whether to select the ith exam and j represents a timeline.
dp[ i ][ j ] = max(dp[ i - 1 ][ j ] ,dp[ i ][ j - chengji[ j ] ])
After listing, it is easy to find that all exams should be sorted according to the end time.
At this time, the complexity of the algorithm is analyzed. According to the idea of knapsack, it is necessary to completely traverse the two-dimensional array. The complexity is 1e8, but the number of students is 1e2, so it will obviously timeout.
This is what we need to simplify our algorithm. After simplification, it is the knowledge point involved in the problem: weighted activity selection problem
After sorting all exams by end time, I need to judge two situations for each exam
① Don't choose this test. At the end of this test, the maximum score I can get is the score of the last test. dp [i] = dp [i-1]
② If this test is selected, the score at the end of this test will be the score obtained in this test + the score at the end of the test at the latest before the start of this test
In ②, since we have sorted all the tests according to the end time, due to the monotonicity, we can use two points in the interval from 1 to i-1 to find the test that ends the latest before the start of the test.
So we can now write a new recurrence: dp [i] = max (dp [I-1], dp [erfen (i-1,test [i]. s)]
When calculating the complexity, an n becomes a logn level, so it becomes a complexity of about 1e7, which can be passed.
In addition, because the starting order of the examination is uncertain, and each student is given the order of the original examination, the original order of the examination should be recorded additionally.
To sum up, you can write the following code
#include<bits/stdc++.h> #define int long long using namespace std; int t,p; double maxn; double stu[105][10005]; double chengji[105][10005]; struct nodep{ double chengji; int i; bool operator < (struct nodep p){ return chengji<p.chengji; } }jidian[105]; struct node{ double s,e,a; int i; bool operator < (struct node p){ return e<p.e|| (e==p.e&&s<p.s); } }test[10005]; int erfen(int r,int start){ int l=1; while(l<=r){ int mid=(l+r)>>1; if(test[mid].e<=start){ l=mid+1; } else{ r=mid-1; } } return r; } signed main(){ cin>>t>>p; cout<<fixed<<setprecision(2); for(int i=1;i<=t;i++){ test[i].i=i; cin>>test[i].s>>test[i].e>>test[i].a; } for(int i=1;i<=p;i++){ for(int j=1;j<=t;j++){ scanf("%lf",&stu[i][j]); stu[i][j]*=test[j].a; } } sort(test+1,test+1+t); for(int i=1;i<=p;i++){ maxn=0; for(int j=1;j<=t;j++){ chengji[i][test[j].i]=max(chengji[i][test[j-1].i],chengji[i][test[erfen(j-1,test[j].s)].i]+stu[i][test[j].i]); maxn=max(maxn,chengji[i][test[j].i]); } jidian[i].chengji=maxn; jidian[i].i=i; } sort(jidian+1,jidian+1+p); for(int i=1;i<=3;i++){ cout<<jidian[p+1-i].i<<" "<<jidian[p+1-i].chengji<<endl; } }