2018-2019 ICPC Northwestern European Regional Programming Contest (NWERC 2018/GYM-102483)

通过的题目:B、G、H、I、K

 

B-Brexit Negotiations(反向拓扑+贪心)

题意:给你n 个会议,依次给出每个会议的持续时间、开这个会议前要开的会议编号,在开每个会议前,要回顾当前会议前的所有会议,每个会议回顾 1 个单位时间,问最长会议的最短时间。

题解:看到诸如前继结点的东西想到拓扑排序,但是建边的时候需要反向建边,用优先队列贪心选择最小t[i]的点,否则如果正向贪心选择最大的t[i],其正确性得不到保障

 

 诸如这种情况的话,正向贪心的时候会把第二个点放到最后,这样会造成贪心策略的错误,事实上反向建边就可避免这种错误。

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define eps 0.000000001
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int maxn=4e5+5;
int tot,head[maxn];
struct E{
    int to,next;
}edge[maxn<<1];
void add(int u,int v){
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
struct node{
    int id,dep;ll t,ans;
}p[maxn];
bool operator <(node a,node b){
    return a.t>b.t;
}
int n,indeg[maxn],dep[maxn];
ll t[maxn],more,ans;
void bfs(){
    priority_queue<node> q;
    rep(i,1,n){
        if(!indeg[i]){q.push(p[i]);}
    }
    while(!q.empty()){
        int now=q.top().id;q.pop();
        ans=max(ans,p[now].t+more);
        for(int i=head[now];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(--indeg[v]==0) q.push(p[v]);
        }
        more--;
    }
}
int main(){
    scanf("%d",&n);mem(head,-1);
    ans=0,more=n-1;
    rep(i,1,n){
        p[i].id=i;
        scanf("%lld",&p[i].t);
        int k;scanf("%d",&k);
        rep(j,1,k){
            int x;scanf("%d",&x);
            add(i,x);indeg[x]++;    
        }
    }
    bfs();
    printf("%lld\n",ans);
}
View Code

 

G-Game Design(思维+模拟)

题意:给你一个字符串(1<=其长度<=20),给你一些操作符"LRUD",表示往某一个方向走直到遇到障碍。现在给定终点(0,0)(0,0),要求构造一个起点以及若干障碍物,使得最后小球能够到达终点。注意必须是最后一步到达终点,中间到达终点即不合法。

第一个样例图如下:

 

 题解:你可以假设从(0,0)开始跑,跑到最后的点作为终点,最后进行平移就好,但是要注意到诸如末尾结束为LRL,RLR,UDU,DUD,这种即为不合法(因为终点是个坑,掉进去就出不来的那种)。所以开局直接特判一下。同时要注意在字符串中间遇到诸如LRLRLR,UDUDUD这种不需要扩大范围。建图的时候一些障碍可能会重叠,但是最后只需要去重一下就行,毕竟没有要求障碍的数目也是最小。具体可以详细见代码。

#include <bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;

int r = 10;
vector<pair<int, int> >a;
map<char, int>mp;
int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    string s; cin >> s;
    int px = 0, py = 0;
    mp['R'] = mp['L'] = 1;
    mp['U'] = mp['D'] = 2;
    if(s.length() >= 3 && s[s.length()-1] == s[s.length()-3] && mp[s[s.length()-1]] == mp[s[s.length()-2]]){
        cout << "impossible" << '\n';
        return 0;
    }
    for(int i = 0; i < s.length(); i++){
        if(i < s.length()-1 && (mp[s[i]] != mp[s[i-1]]))
            r += 5;
        if(s[i] == 'R') { px = r; a.push_back({px+1, py}); }
        else if(s[i] == 'L') {px = -r; a.push_back({px-1, py}); }
        else if(s[i] == 'U') {py = r; a.push_back({px, py+1}); }
        else if(s[i] == 'D') {py = -r; a.push_back({px, py-1}); }
    }
    for(int i = 0; i < a.size(); i++){
        a[i].first -= px; a[i].second -= py;
    }
    a.pop_back();
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());
    cout << -px << " " << -py << '\n';
    cout << a.size() << '\n';
    for(int i = 0; i < a.size(); i++){
        cout << a[i].first << " " << a[i].second << '\n';
    }
}
View Code

 

posted @ 2020-09-05 20:06  Anonytt  阅读(247)  评论(0编辑  收藏  举报