• codeforces round 433 D. Jury Meeting


    题目大意:

    输入n,m,k,分别代表城市的数量,城市编号1~n,航班的数量以及会议必须所有人员到会一起商议的天数,然后及时输入m行航班的信息,每一行输入d,f,t,c分别表示航班到站和始发的那一天(始发和到站是一天),f表示始发站,t表示目的地,c表示花费,然后f和t里必然有一个是0,表示要么是去0号城市,要么回到原来城市,题目要求就是,每个城市必须派人到0号城市参加会议,然后他们必须一块在0号城市k天,然后必须全部回到他们原来的城市才行(某个城市某个人到达0号城市之后可以愿意待多少天就待多少天,当然,回不去就尴尬了),让你求最小的花费,如果不能满足条件,输出-1;

    基本思路:

    最小费用分为0号城市的航班的费用和从0号城市飞回的费用,分别处理,然后贪心的话,就有一个问题,拿飞向0号城市的航班来说,到底是按照始发时间排序还是按照费用排序,想一下,如果按照费用排序,这个时间复杂度肯定过不了,那么就按照始发时间排序,这样,用一个dp数组记录总费用,下标是这n个航班的最晚始发时间,然后对于某一个最晚始发时间,最优的肯定是它和始发时间在它前面的最小费用了,然后就有这个dp【i】=min(dp【i-1】,dp【i】),这个点之前的最小费用就这样传递了过来,然后这样时间复杂度就是n,完全没问题;

    反思与总结:

    我只知道是贪心,并没有明确的贪心思路,看了题解才发现,类似的题目我也做过2个,真心菜,一定要扎实,首要目的是下次能a出这个题目啊;

    代码如下:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    const ll inf = 1e17;
    const int maxn = 2000000+10;
    const int maxx = 100000+10;
    
    struct Node
    {
        int d,f,t,c;
        bool operator<(const Node& a)const {return d<a.d;}
    }node[maxx];
    ll dp1[maxn],dp2[maxn],b[maxn];
    
    
    int main()
    {
        int n,m,k;
        while(scanf("%d%d%d",&n,&m,&k)==3)
        {
            for(int i=0;i<=maxn;i++) dp1[i]=inf,b[i]=-1;
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d%d%d",&node[i].d,&node[i].f,&node[i].t,&node[i].c);
            }
            sort(node+1,node+m+1);
            int cnt=0;
            ll sum=0;
            for(int i=1;i<=m;i++)
            {
                if(node[i].f==0) continue;
                if(b[node[i].f]==-1)
                {
                    b[node[i].f]=node[i].c;
                    sum+=node[i].c;
                    cnt++;
                }
                else
                {
                    if(b[node[i].f]>node[i].c)
                    {
                        sum-=b[node[i].f];
                        sum+=node[i].c;
                        b[node[i].f]=node[i].c;
                    }
                }
                if(cnt==n) dp1[node[i].d]=sum;
            }
            sum=0;
            cnt=0;
            for(int i=0;i<=maxn;i++) dp2[i]=inf,b[i]=-1;
            for(int i=m;i>=1;i--)
            {
                if(node[i].t==0) continue;
                if(b[node[i].t]==-1)
                {
                    b[node[i].t]=node[i].c;
                    sum+=node[i].c;
                    cnt++;
                }
                else
                {
                    if(b[node[i].t]>node[i].c)
                    {
                        sum-=b[node[i].t];
                        sum+=node[i].c;
                        b[node[i].t]=node[i].c;
                    }
                }
                if(cnt==n) dp2[node[i].d]=sum;
            }
            int sign;
            for(int i=1;i<=maxn;i++) if(dp1[i]!=inf) {sign=i;break;}
            for(int i=sign;i<=1000000;i++) dp1[i]=min(dp1[i],dp1[i-1]);
            for(int i=1000000;i>=1;i--) if(dp2[i]!=inf) {sign=i;break;}
            for(int i=sign-1;i>=1;i--) dp2[i]=min(dp2[i],dp2[i+1]);
            ll res=inf;
            for(int i=1;i<=1000000;i++)
            {
                if(dp1[i]==inf||dp2[i+k+1]==inf) continue;
                res=min(res,dp1[i]+dp2[i+k+1]);
            }
            if(res==inf) printf("-1
    ");
            else printf("%I64d
    ",res);
        }
        return 0;
    }
    
  • 相关阅读:
    进程、线程
    timer控件、三级联动
    用户控件、动态创建添加
    打印控件
    窗体移动和阴影,对话框控件
    winform listview控件
    winform打开唯一窗体、构造函数传值
    菜单和工具栏
    winform公共控件
    hibernate中各种包的添加
  • 原文地址:https://www.cnblogs.com/imzscilovecode/p/7490696.html
Copyright © 2020-2023  润新知