照学校ppt上写:
#include<iostream>
#include<algorithm>
using namespace std;
int n;
struct Job {
int D;
int P;
bool operator<(Job& j)
{
if(P==j.P)
return D<j.D;
return P > j.P;
}
};
Job Jobs[1000005];
int J[1000005];
int main()
{
scanf("%d",&n);
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &Jobs[i].D, &Jobs[i].P);
}
sort(Jobs + 1, Jobs + n + 1);
J[1] = 1;
long long res = 0;
res += Jobs[1].P;
int k = 1, i = 0, r = 0;
for (int i = 2; i <= n; i++)
{
r = k;
while (Jobs[J[r]].D > Jobs[i].D && Jobs[J[r]].D != r)
{
r = r - 1;
}
if (Jobs[J[r]].D <= Jobs[i].D && Jobs[i].D > r)
{
for (int l = k; l >= r + 1; l--)
{
J[l + 1] = J[l];
}
J[r + 1] = i;
res += Jobs[i].P;
k = k + 1;
}
}
cout<<res;
}
经验:比较大的数组,如果开在某个main函数里或者某个函数里,往往会导致爆栈(stack overflow), 应该尽量多用堆区少用栈区,把大数组开在全局即可
优化写法:
学校ppt上的算法实现一般都挺蠢的,用插入排序来维护最优解,时间复杂度太高了,
实际上这个问题的最优做法就是“能拖则拖”,把每个作业,尽量放到他允许的期限的最后一个时间片,如果不行则往前放,如果前面整个都没有空位了,那这个作业只能舍弃了,所以对每个作业,从它的期限开始往小枚举,能用则用,不能则往小考虑,若全部不行,则舍弃,并且更新最小值min值,min其实代表的含义就是最小的可用时间片。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
struct job {
int power;
int time;
};
bool cmp(job a, job b)
{
if (a.power == b.power)
return a.time < b.time;
return a.power > b.power;
}
int main()
{
int n = 0;
cin >> n;
job jobs[1000005];
int max = 0;
int min=1;
for (int i = 0; i < n; i++)
{
cin >> jobs[i].time >> jobs[i].power;
if (jobs[i].time > max)
max = jobs[i].time;
}
sort(jobs, jobs + n, cmp);
bool* used = new bool[max + 1]{};
long p = 0;
for (int i = 0; i < n; i++)
{
for (int j = jobs[i].time; j >=min; j--)
{
if (!used[j])
{
used[j] = true;
p += jobs[i].power;
break;
}
if(j==min)
min=jobs[i].time;
}
}
cout << p;
}