• codeforces730I Olympiad in Programming and Sports(姿势题 优先队列?dp?)


    题意:

    给你s(3000)个人,有两个社团,分别招收n和m(n+m<=s)个人,

    每个人对这两个社团分别有一个自己的喜爱值(3000),

    问怎样安排使得总的喜爱值最大,spj

    思路:

    如果n+m==s的话,裸的n^2的dp记一下前驱。。然而可以小于的话,

    我除了n^3的就没有其他思路了。。。(弱就是弱)

    看了看别人的代码,大概懂了,就是先把对第一个社团最喜爱的n个人放入,

    然后对于第二个社团,每放一个人,就比较一下:

    还没有加入社团的人(1)对第一个社团贡献最大的人的贡献+在第一个社团中的人(2)如果转到第二个社团所得到的最大贡献

    和还没有加入这团的人(3)对第二个社团贡献最大的人的贡献做比较

    如果前者大,就把(2)从第一个社团调到第二个社团,然后把(1)加入第一个社团

    反之则把(3)加入第二个社团。

    这样重复m次,就完成了

    对于维护这三类,用三个优先队列吧。

    /* ***********************************************
    Author        :devil
    ************************************************ */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <stack>
    #include <map>
    #include <string>
    #include <time.h>
    #include <cmath>
    #include <stdlib.h>
    #define LL long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define dep(i,a,b) for(int i=a;i>=b;i--)
    #define ou(a) printf("%d
    ",a)
    #define pb push_back
    #define pii pair<int,int>
    #define mkp make_pair
    #define IN freopen("in.txt","r",stdin);
    #define OUT freopen("out.txt","w",stdout);
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    const int N=3e3+10;
    int s,n,m,a[N],b[N],c[N],ans;
    priority_queue<pii>p1,p2,tmp;
    int main()
    {
        scanf("%d%d%d",&s,&n,&m);
        for(int i=1;i<=s;i++) scanf("%d",&a[i]),p1.push(mkp(a[i],i));
        for(int i=1;i<=s;i++) scanf("%d",&b[i]),p2.push(mkp(b[i],i));
        while(n--)
        {
            int u=p1.top().second;
            p1.pop();
            c[u]=1;
            ans+=a[u];
            tmp.push(mkp(b[u]-a[u],u));
        }
        while(m--)
        {
            while(!p1.empty()&&c[p1.top().second]) p1.pop();
            while(!p2.empty()&&c[p2.top().second]) p2.pop();
            if(p1.top().first+tmp.top().first>p2.top().first)
            {
                int u=p1.top().second,v=tmp.top().second;
                p1.pop();tmp.pop();
                c[u]=1;c[v]=2;
                tmp.push(mkp(b[u]-a[u],u));
                ans+=b[v]-a[v]+a[u];
            }
            else
            {
                int u=p2.top().second;
                p2.pop();
                c[u]=2;
                ans+=b[u];
            }
        }
        printf("%d
    ",ans);
        for(int i=1;i<=s;i++) if(c[i]==1) printf("%d ",i);
        printf("
    ");
        for(int i=1;i<=s;i++) if(c[i]==2) printf("%d ",i);
        return 0;
    }
  • 相关阅读:
    20165322 第九周 实现mypwd
    20165322 第七周 mybash 的实现
    2018-2019-1 20165322 实验三 实时系统
    2018-2019-1 20165318 20165322 20165326 实验二 固件程序设计
    2018-2019-1 20165322 《信息安全系统设计基础》第六周学习总结
    codeblocks汉化
    2019-2020-1 20175334 实验五 《通讯协议设计》实验报告
    2019-2020-1 20175334 20175322 20175315 实验四 外设驱动程序设计
    2019-2020-1 20175315 20175322 20175334 实验三 实时系统
    2019-2020-1 20175334 20175322 20175315 实验二 固件程序设计
  • 原文地址:https://www.cnblogs.com/d-e-v-i-l/p/6126662.html
Copyright © 2020-2023  润新知