51nod 1163 最高奖励 已AC 刷题过程记录

基准时间限制: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出来

这个优化想了好久, 

结果是对的 ,但是最后几组数据超时了。

现在在纠结。 - - 这个也借鉴了迪杰斯特拉的思想。  

模拟队列,去掉无用的树枝

- - 考虑一下要不要看看题解- -  

明天再战一波







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值