码迷,mamicode.com
首页 > 其他好文 > 详细

CF 题目选做

时间:2019-09-08 22:23:54      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:src   cto   return   ack   http   直接   using   long   event   

  写省选的题目对noip没什么大用 关键是 细节题或者是思考题比较重要 练思维自然是CF比较好了 把我见到的比较好的CF题放上来刷一刷。

LINK:Complete the projects

就是说一个人 初始值为R 有n项工作每项工作有两种属性 a和b 当且仅当 R>=a时可以完成这项任务 且R+=b; 每项任务只能完成一次 问能否把所有工作完成。注:b可能为负。

怎么做?显然对于b>=0的工作我们按照a由小到大的顺序直接做如果有不能完成的任务的话 那便一定不能完成。考虑如何做负值的工作?

想了一下我们不能仅仅按照a的值从大到小做 因为可能出现顺序上的错误 导致答案错误 按照 ai+bi从大到小的顺序么? 经过我的一番操作 发现wa掉了。再次考虑这个顺序?

苦苦思索好多天 发现没认真读题 题目中说道对于完成每一个任务都R都得非负,最后我没判断R的正负... 所以就是按照ai+bi从大到小的顺序的。

当时考的时候我直接想到了 但是没想证明这里来利用微扰法来证明一下。设当前任务排序为 a1+b1,a2+b2...an+bn;

如果对于 ai+bi >aj+bj 来说j排在i前面那么 则有R>=aj 且R-=bj 之后可得 R>=ai; 我们看另一种情况 R>=ai 且 R-=bi 之后又 R>=aj;

好像不太好证明  因为看起来非常的显然 也容易想到,那么不证自明好了.../cy

技术图片
//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<ctime> 
#include<cstring>
#include<string>
#include<ctime>
#include<cctype>
#include<cstdio>
#include<utility>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
#include<bitset>
#include<vector>
#include<algorithm>
#include<cstdlib>
#define ll long long
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline ll read()
{
    ll x=0,f=1;char ch=getc();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getc();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getc();}
    return x*f;
}
const ll MAXN=210;
ll n,r,top,top1,flag;
struct wy
{
    ll x,y;
}t[MAXN],w[MAXN];
inline ll cmp(wy a,wy b){return a.x<b.x;}
inline ll cmp1(wy a,wy b){return a.x+a.y>b.x+b.y;}
int main()
{
    //freopen("1.in","r",stdin);
    n=read();r=read();
    for(ll i=1;i<=n;++i)
    {
        ll x,y;
        x=read();y=read();
        if(y>=0)t[++top]=(wy){x,y};
        if(y<0)w[++top1]=(wy){x,y};
    }
    sort(t+1,t+1+top,cmp);
    for(ll i=1;i<=top;++i)
    {
        if(t[i].x>r){puts("NO");return 0;}
        r+=t[i].y;
    }
    sort(w+1,w+1+top1,cmp1);
    for(ll i=1;i<=top1;++i)
    {
        if(w[i].x>r){puts("NO");return 0;}
        r+=w[i].y;
    }
    if(r>=0)puts("YES");
    else puts("NO");
    return 0;
}
View Code

LINK:加强版

现在是求 我们最多能完成的任务数 这就很有区别了首先对于b>=0我们不一定能全部做完但是还是可以贪心的去做 因为拿不到的不管采取什么方法都拿不到。

考虑如何取 a<0的部分这次我们不能再贪心的选取了 因为 可能当前是能选导致R大大减小 以至于后面选的任务更少了。

但是我们仍可以按照上一道题的排序方式来选取,这样仍可以使得利益最大化...固定了顺序接下来的操作其实就是对于每个任务选或不选了,直接背包的拿取即可。dp一下...

当然和背包不太一样因为 有ai的限制我们状态设为 到第i个任务此时R值为j所做的最多的任务数,这样进行转移即可。只不过这个需要刷表法更容易写。

技术图片
//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<ctime> 
#include<cstring>
#include<string>
#include<ctime>
#include<cctype>
#include<cstdio>
#include<utility>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
#include<bitset>
#include<vector>
#include<algorithm>
#include<cstdlib>
#define ll long long
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getc();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getc();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getc();}
    return x*f;
}
const int MAXN=110,maxn=30010<<1;
int n,r,top,top1,ans,maxx;
int f[MAXN][maxn];//f[i][j]表示到了第i个任务此时还有j所能完成的最大任务数
struct wy
{
    int x,y;
}t[MAXN],w[MAXN];
inline int cmp(wy a,wy b){return a.x<b.x;}
inline int cmp1(wy a,wy b){return a.x+a.y>b.x+b.y;}
int main()
{
    //freopen("1.in","r",stdin);
    n=read();r=read();
    for(int i=1;i<=n;++i)
    {
        int x,y;
        x=read();y=read();
        if(y>=0)t[++top]=(wy){x,y};
        if(y<0)w[++top1]=(wy){x,y};
    }
    sort(t+1,t+1+top,cmp);
    for(int i=1;i<=top;++i)
    {
        if(t[i].x>r)break;
        r+=t[i].y;++ans;
    }
    sort(w+1,w+1+top1,cmp1);
    for(int i=1;i<=top1;++i)
    {
        for(int j=0;j<=r;++j)
        {
            f[i+1][j]=max(f[i+1][j],f[i][j]);
            if(j>=w[i].x&&j>=w[i].y)f[i+1][j+w[i].y]=max(f[i+1][j+w[i].y],f[i][j]+1);
        }
    }
    for(int j=0;j<=r;++j)maxx=max(maxx,f[top1+1][j]);
    printf("%d\n",maxx+ans);
    return 0;
}
View Code

 

CF 题目选做

标签:src   cto   return   ack   http   直接   using   long   event   

原文地址:https://www.cnblogs.com/chdy/p/11488456.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!