2018-2019 ICPC Northwestern European Regional Programming Contest (NWERC 2018)训练记录

B    Brexit Negotiations

题意:有n个会议,对于会议i,它将花费时间ci,并需要在进行前先完成指定的di个会议。在每个会议中,将为在它之前进行的每个会议各花费1个单位的时间。现在要为这n个会议进行排序,使得其中进行时间最长的会议时间最短。

思路:从每个会议进行前需要完成若干个指定会议这一点可以看出,

可以在(会议i)<--(会议i进行前需要进行的会议)之间连有向边,使用拓扑排序就可求出会议进行顺序。

对于第i个进行的会议,它的时长为c+i。

粗略地想,我们应当选择当前能够进行并且时间最长的会议,

于是想到使用优先队列,在拓扑排序过程中,将ci值大的先取出进行删边。

但是仔细一想,这种贪心没有考虑到当前不满足进行条件但时间很长的会议。

于是先使用dfs,求出所有需要先进行会议i的(cj+(会议i与会议j的距离))的最大值dis[i],将dis值大的先取出进行删边。

(具体看代码)

。。看了一圈题解,发现只要反向建边就可以直接拓扑了。啊这。。

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=400005;
struct node
{
    int id,dis,t;
    node() {}
    node(int a,int b,int c) 
    {
        id=a;
        dis=b;
        t=c;
    }
    bool operator < (const node &b) const
    {
        return dis<b.dis;
    }
};
priority_queue<node>q;
int n,a[maxn],in[maxn],last[maxn],num;
int dis[maxn],vis[maxn],ans;
struct edge
{
    int to,nxt;
}e[maxn];
void add(int x,int y)
{
    e[++num].to=y;
    e[num].nxt=last[x];
    last[x]=num;
}
int topo()
{
    for (int i=1;i<=n;i++) 
        if (!in[i]) q.push(node(i,dis[i],a[i]));
    int now=0,ans=0;
    node x;
    while (!q.empty())
    {
        x=q.top();
        q.pop();
        ans=max(ans,now+x.t);
        now++;
        for (int i=last[x.id];i;i=e[i].nxt)
        {
            in[e[i].to]--;
            if (in[e[i].to]==0) q.push(node(e[i].to,dis[e[i].to],a[e[i].to]));
        }
    } 
    return ans;
}
void dfs(int x)
{
    vis[x]=1;
    dis[x]=a[x];
    for (int i=last[x];i;i=e[i].nxt)
    {
        if (!vis[e[i].to]) dfs(e[i].to);
        dis[x]=max(dis[x],dis[e[i].to]+1);
    }
} 
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i],&in[i]);
        for (int j=1,u;j<=in[i];j++)
        {
            scanf("%d",&u);
            add(u,i);
        }
    }
    for (int i=1;i<=n;i++)
        if (!in[i]) dfs(i);
    printf("%d
",topo());
    return 0;
}
View Code

G

题意:有一个n*n的迷宫,迷宫中有若干个方块。球从某个起点开始,要最终走到终点(0,0)。每次操作可以走上下左右四个方向,直至碰到方块或者边界球才停止。现在给出一串操作,要求设计球的起点和迷宫中方块的分布,使得球能够根据这串操作走至终点。

思路:一开始想着从终点开始倒着做,发现很难想。看了别人的代码,发现直接正着做会好做一点。

()

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
vector<pair<int,int> >a;
int dir[100];
char s[25];
int main()
{
    int i,x=0,y=0,len,r=1;//先假装起点为0,0 
    scanf("%s",s);
    dir['R']=dir['L']=1;
    dir['U']=dir['D']=2;
    len=strlen(s); 
    if (len>=3 && s[len-1]==s[len-3] && dir[s[len-1]]==dir[s[len-2]])
    {
        printf("impossible
");
        return 0;
    }
    for (i=0;i<len;i++)
    {
        if (i<len-1 && dir[s[i]]!=dir[s[i-1]]) r++;
        if (s[i]=='R') 
        { 
            x=r;
            a.push_back({x+1,y}); 
        }
        else if (s[i]=='L') 
        {
            x=-r; 
            a.push_back({x-1,y}); 
        }
        else if (s[i]=='U') 
        {
            y=r; 
            a.push_back({x,y+1});
        }
        else if (s[i]=='D') 
        {
            y=-r; 
            a.push_back({x,y-1}); 
        }
    }
    for (i=0;i<a.size();i++)
    {
        a[i].first-=x;
        a[i].second-=y;
    }
    sort(a.begin(),a.end());
    a.erase(unique(a.begin(),a.end()),a.end());//去重 
    printf("%d %d
",-x,-y);//根据终点为0,0,修改起点坐标为0-x,0-y 
    printf("%d
",a.size());
    for (i=0;i<a.size();i++) printf("%d %d
",a[i].first,a[i].second);
    return 0;
}
View Code

H    Hard Drive

I    Inflation

题意:有n个气球,容量从1到n,同时有n个气瓶,有a[i]容量的气。当给气球充气的气瓶的容量大于气球的,那么气球就会爆炸,

找出一种气球与气瓶的配对,使得没有气球爆炸并且所有配对中a[i]/i的最小值最大,输出这个最小值。

思路:直接将a排序,然后两两配对就行了。

注意答案直接输出就行了,special judge

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200005;
int a[maxn];
int main()
{
    int i,n,flag;
    double ans,tmp;
    scanf("%d",&n);
    for (i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    ans=1.0;
    flag=0;
    for (i=1;i<=n;i++)
    {
        if (a[i]>i) 
        {
            flag=1;
            break;
        }
        else 
        {
            tmp=(double)a[i]/i;
            ans=min(ans,tmp);
        }
    }
    if (!flag) printf("%lf
",ans);
    else printf("-1
");
    return 0;
} 
View Code

K    Kleptography

原文地址:https://www.cnblogs.com/lsykk/p/13768723.html