基准时间限制:1 秒 空间限制:131072 KB 分值: 20
难度:3级算法题
有N个任务,每个任务有一个最晚结束时间以及一个对应的奖励。在结束时间之前完成该任务,就可以获得对应的奖励。完成每一个任务所需的时间都是1个单位时间。有时候完成所有任务是不可能的,因为时间上可能会有冲突,这需要你来取舍。求能够获得的最高奖励。
Input
第1行:一个数N,表示任务的数量(2 <= N <= 50000) 第2 - N + 1行,每行2个数,中间用空格分隔,表示任务的最晚结束时间E[i]以及对应的奖励W[i]。(1 <= E[i] <= 10^9,1 <= W[i] <= 10^9)
Output
输出能够获得的最高奖励。
Input示例
7 4 20 2 60 4 70 3 40 1 30 4 50 6 10
Output示例
230
这个是ac代码 ,用到的是贪心的思想
大致就是我们倒着想,比如说,倒数第一天能做的任务中,留谁最好。
然后 倒数第二天中,留谁最好。
这样就是从 每天 ,能做的任务中,选取最大的
比如倒数第一天,能做的是大于等于倒数第一天时间的任务。
险过的代码。 过几天队列优化下,
但是这个代码实现的思想是最根本的东西。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <iomanip>
using namespace std;
struct yu
{
long long x,y;
}
d[50005];
bool cmp(yu a,yu b)
{
return a.x<b.x;
}
int main()
{
long long n;
while(cin>>n)
{
memset(d,0,sizeof(d));
for(long long i=0;i<n;i++)
{
cin>>d[i].x>>d[i].y;
}//cout<<endl;
sort(d,d+n,cmp);
//for(long long i=0;i<n;i++)cout<<d[i].x<<' '<<d[i].y<<endl;cout<<endl;
long long t=n,l=0;
long long sum=0,maxs,maxsl;
for(long long t=n;t>=1;t--)
{
maxs=0;
maxsl=n+1;
for(long long j=n-1;j>=0;j--)//倒着找最优的值。
{
if(d[j].x<t) break;
//cout<<d[j].x<<' '<<d[j].y<<' '<<j<<endl;
if(d[j].y>maxs)
{
maxs=d[j].y;
maxsl=j;
}
}
//cout<<maxs<<' '<<d[maxsl].x<<' '<<t<<' '<<sum<<endl;
sum+=maxs;
d[maxsl].y=0;
}
cout<<sum<<endl;
}
}
下面是刷题过程记录。
= = 这个加法卡了我几分钟,
之后发现可以当成背包算
每个物品放或者不放。
先写个搜索暴力跑结果 之后
正确答案但是超时的代码如下
#include <iostream>
#include <algorithm>
using namespace std;
long long maxs;
long long n;
long long tag[10000];//此数组为标记一个数的和的组合是什么。
struct yu
{
long long x,y;
}
d[50000];
bool cmp(yu a,yu b)
{
return a.x<b.x;
}
void dfs(long long s,long long l,long long t)
{
if(s>maxs)
{
cout<<t<<' '<<s<<' '<<l<<endl;
for(int i=0;i<t;i++)//查看组合是啥
cout<<tag[i]<<' ';
cout<<endl;
maxs=s;
}
if(l==n) return ;
if(t<d[l].x)
{
tag[t]=d[l].y;
dfs(s+d[l].y,l+1,t+1);
tag[t]=0;
}
dfs(s,l+1,t);
}
int main()
{
while(cin>>n)
{
maxs=0;
for(long long i=0;i<n;i++)
cin>>d[i].x>>d[i].y;
cout<<endl;
sort(d,d+n,cmp);
//for(long long i=0;i<n;i++) cout<<d[i].x<<' '<<d[i].y<<endl;
dfs(0,0,0);
cout<<maxs<<endl;
}
}
然后 看样例之后 发现组合里面是有规律的 就是 ,同等时间下,优选最大的。
然后这里找到了贪心的意思。
就是每个时间下,留下的值为最大。
贪心也属于动态规划。
= = 然后 剩下的考完试再说
#include <iostream>
#include <algorithm>
#include <cstring>
#include <iomanip>
using namespace std;
long long maxs;
long long n;
const long long mod=4999999;
long long tag[10000];
long long s[5000000],l[5000000],t[5000000];
long long dp[100000];
struct yu
{
long long x,y;
}
d[50005];
bool cmp(yu a,yu b)
{
return a.x<b.x;
}
int main()
{
while(cin>>n)
{
maxs=0;
memset(s,0,sizeof(s));
memset(l,0,sizeof(l));
memset(t,0,sizeof(t));
memset(dp,-1,sizeof(dp));
for(long long i=0;i<n;i++)
cin>>d[i].x>>d[i].y;
//cout<<endl;
sort(d,d+n,cmp);
// for(long long i=0;i<n;i++) cout<<d[i].x<<' '<<d[i].y<<endl;
long long x=0,y=1;
long long z=1;
int sum=0;
while(y+1!=x)
{
z=1;
if(dp[t[x]]<=s[x]&&l[x]<n&&t[x]<d[l[x]].x)
{
z=0;
s[y]=s[x]+d[l[x]].y;
l[y]=l[x]+1;
t[y]=t[x]+1;
if(maxs<s[y]) maxs=s[y];
if(s[y]>dp[t[y]]) dp[t[y]]=s[y];
//cout<<x<<' '<<y<<' '<<z<<' '<<s[x]<<' '<<s[y]<<' '<<l[x]<<endl;
y=(y+1)%mod;
}
if(dp[t[x]]<=s[x]&&l[x]<n)
{
z=0;
s[y]=s[x];
l[y]=l[x]+1;
t[y]=t[x];
if(dp[t[x]]<s[x]) dp[t[y]]=s[y];
//cout<<x<<' '<<y<<' '<<z<<' '<<s[y]<<endl;
y=(y+1)%mod;
}
if(y==0) sum++;
x=(x+1)%mod;
}
//cout<<sum<<endl;
/*
for(long long i=0;i<y;i++) cout<<setw(5)<<i;cout<<endl;
for(long long i=0;i<y;i++) cout<<setw(5)<<s[i];cout<<endl;
for(long long i=0;i<y;i++) cout<<setw(5)<<l[i];cout<<endl;
for(long long i=0;i<y;i++) cout<<setw(5)<<t[i];cout<<endl;
*/
cout<<maxs<<endl;
}
}
虽然考完试了
但是还是没有能a出来
这个优化想了好久,
结果是对的 ,但是最后几组数据超时了。
现在在纠结。 - - 这个也借鉴了迪杰斯特拉的思想。
模拟队列,去掉无用的树枝
- - 考虑一下要不要看看题解- -
明天再战一波