2020杭电多校第四场

1002.Blow up the Enemy

先把最优的武器选出来,花最少时间能打死对面那种(不止一个)

父亲想赢的话就只有赌中这些最优的武器概率为cnt/n,选出来了也只有1/2的概率赢

最后我赢的概率就是父亲输的概率 ,1-cnt/2n

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (register int i = a; i <= b; i++)

int n, a, b;
int tmp, cnt, mt;
inline void solve()
{
    cin >> n;
    mt = 1e9;
    rep(i, 1, n)
    {
        cin >> a >> b;
        tmp = 100 / a;
        if (100 % a == 0)
            tmp--;
        tmp *= b;
        if (tmp == mt)
            cnt++;
        else if (tmp < mt)
        {
            cnt = 1;
            mt = tmp;
        }
    }
    cout << 1.0 * (2 * n - cnt) / (2 * n) << endl;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
}
View Code

 

1004.Deliver the Cake

最短路问题,经过某些村庄必须停留换手。。

直接上Dijkstra,考虑经过M的时候把他拆成l,r两个点。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (register int i = a; i <= b; i++)

struct edges
{
    int to, next, w;
} e[400010];
int id, head[100010];
inline void add(int x, int y, int w)
{
    e[++id].w = w;
    e[id].to = y;
    e[id].next = head[x];
    head[x] = id;
}
struct node
{
    unsigned long long u, d, flag;
    bool operator<(const node &f) const { return d > f.d; }
};
priority_queue<node> q;

unsigned long long n, m, s, v, x;
char str[100010];
int dir[100010], vis[100010][3];
unsigned long long dis[100010][3];

inline void solve()
{
    cin >> n >> m >> s >> v >> x;
    cin >> str;
    rep(i, 0, n - 1) if (str[i] == 'M')
        dir[i + 1] = 0;
    else if (str[i] == 'L') dir[i + 1] = 1;
    else if (str[i] == 'R') dir[i + 1] = 2;

    id = 0;
    memset(e, 0, sizeof(e));
    rep(i, 1, n)
    {
        dis[i][1] = dis[i][2] = 1e16;
        head[i] = vis[i][1] = vis[i][2] = 0;
    }
    int a, b, w;
    rep(i, 1, m)
    {
        cin >> a >> b >> w;
        add(a, b, w);
        add(b, a, w);
    }
    if (dir[s])
    {
        q.push((node){s, 0, dir[s]});
        dis[s][dir[s]] = 0;
    }
    else
    {
        q.push((node){s, 0, 1});
        q.push((node){s, 0, 2});
        dis[s][1] = dis[s][2] = 0;
    }
    while (!q.empty())
    {
        s = q.top().u;
        int flag = q.top().flag, flag2;
        q.pop();
        if (vis[s][flag])
            continue;
        vis[s][flag] = 1;
        for (int i = head[s]; i; i = e[i].next)
        {
            ll tmp = dis[s][flag] + e[i].w;
            flag2 = dir[e[i].to];
            if (flag2)
            {
                if (flag != flag2)
                    tmp += x;
                if (!vis[e[i].to][flag2] && dis[e[i].to][flag2] > tmp)
                {
                    dis[e[i].to][flag2] = tmp;
                    q.push((node){e[i].to, dis[e[i].to][flag2], flag2});
                }
            }
            else
            {
                if (!vis[e[i].to][flag] && dis[e[i].to][flag] > tmp)
                {
                    dis[e[i].to][flag] = tmp;
                    q.push((node){e[i].to, dis[e[i].to][flag], flag});
                }
                if (!vis[e[i].to][3 - flag] && dis[e[i].to][3 - flag] > tmp + x)
                {
                    dis[e[i].to][3 - flag] = tmp + x;
                    q.push((node){e[i].to, dis[e[i].to][3 - flag], 3 - flag});
                }
            }
        }
    }
    if (dir[v])
        cout << dis[v][dir[v]] << endl;
    else
        cout << min(dis[v][1], dis[v][2]) << endl;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
}
View Code

 

1005.Equal Sentences

每个单词出现的位置不能差超过1的长度,这就限制了只能相邻的两个单词交换。

相同的单词不能交换,那就记录下当前位置种类数。

dp[i][0]表示与上一个位置不交换,dp[i][0] = dp[i-1][0] + dp[i-1][1]

dp[i][1]表示与上一个位置交换,如果当前单词与上一个相等,则dp[i][1]=0,不相等dp[i][1] = dp[i-1][0]

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (register int i = a; i <= b; i++)

int mod = 1e9 + 7;
int n;
char a[100010][15];
int vis[100010], dp[100010][2];
inline void solve()
{
    memset(a, 0, sizeof(a));
    cin >> n;
    rep(i, 1, n)
    {
        scanf("%s", a[i]);
        dp[i][0] = dp[i][1] = 0;
        vis[i] = strcmp(a[i], a[i - 1]) == 0;
    }
    dp[1][0] = 1;
    rep(i, 2, n)
    {
        dp[i][0] = (dp[i - 1][0] + dp[i - 1][1]) % mod;
        dp[i][1] = vis[i] ? 0 : dp[i - 1][0];
    }
    cout << (dp[n][0] + dp[n][1]) % mod << endl;
}
int main()
{
    // ios_base::sync_with_stdio(0);
    // cin.tie(0);
    // cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
}
View Code

 

1007.Go Running

每个人只能往某一个方向跑,告诉你 t 时刻在 x 位置有人,问最少有多少个人。

由于只能往一个方向跑,那么x和t和或者差相等的一些点可以分为一个人,

把(t,x)点对画在坐标轴上,一条斜率为1或者-1的直线就表示一个人,

坐标轴旋转一下,就简化成画多少条平行于坐标轴的直线能将平面上的点覆盖,

这就简化成了二分图的经典模型,将每个点横坐标向纵坐标连边,求最大匹配。

匈牙利算法复杂度O(n2),这里用网络流dinic O(n√n)的方式解决

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (register int i = a; i <= b; i++)

struct edge
{
    int to, next, w;
} e[600100];
int id, head[200100];
void add(int x, int y)
{
    e[++id] = (edge){y, head[x], 1};
    head[x] = id;
    e[++id] = (edge){x, head[y], 0};
    head[y] = id;
}

int n, a[100010], b[100010], mia[100010], mib[100010];
int s, v, ans;

int dis[200100];
queue<int> q;
bool bfs()
{
    rep(i, 1, v) dis[i] = -1;
    dis[s] = 0;
    q.push(s);
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i = head[u]; i; i = e[i].next)
            if (dis[e[i].to] == -1 && e[i].w > 0)
            {
                dis[e[i].to] = dis[u] + 1;
                q.push(e[i].to);
            }
    }
    return dis[v] != -1;
}
int dfs(int u, int limit)
{
    if (u == v)
        return limit;
    int flow = 0, tmp = 0;
    for (int i = head[u]; i; i = e[i].next)
    {
        if (dis[e[i].to] == dis[u] + 1 && e[i].w > 0)
        {
            tmp = dfs(e[i].to, min(limit, e[i].w));
            if (!tmp)
                continue;
            limit -= tmp;
            flow += tmp;
            e[i].w -= tmp;
            e[i ^ 1].w += tmp;
            if (!limit)
                break;
        }
    }
    return flow;
}
inline void solve()
{
    cin >> n;
    id = 1;
    memset(head, 0, sizeof(head));
    memset(e, 0, sizeof(e));
    int aa, bb;
    rep(i, 1, n)
    {
        cin >> aa >> bb;
        mia[i] = a[i] = bb + aa;
        mib[i] = b[i] = bb - aa;
    }
    sort(mia + 1, mia + n + 1);
    sort(mib + 1, mib + n + 1);
    int na = unique(mia + 1, mia + n + 1) - mia - 1;
    int nb = unique(mib + 1, mib + n + 1) - mib - 1;
    s = na + nb + 1;
    v = s + 1;
    map<int, int> mpa, mpb;
    rep(i, 1, na)
    {
        mpa[mia[i]] = i;
        add(s, i);
    }
    rep(i, 1, nb)
    {
        mpb[mib[i]] = i + na;
        add(i + na, v);
    }
    rep(i, 1, n) add(mpa[a[i]], mpb[b[i]]);

    ans = 0;
    while (bfs())
        ans += dfs(s, 1e9);
    cout << ans << endl;
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
}
View Code

 

1011.Kindergarten Physics

签到题!算得正嗨,队友说直接输出(d-1).9999999

题解也是直接输出d

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (register int i = a; i <= b; i++)

int a, b, c, d;
inline void solve()
{
    cin >> a >> b >> c >> d;
    cout << c - 1 << ".999999999\n";
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
}
View Code

 

1012.Last Problem

构造题,要在(x,y)位置填n,必须要在四周填n-1,n-2,n-3,n-4。

暴搜,让n-1,n-4在两侧,n-2,n-3在两侧可以减少重复填数的次数。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (register int i = a; i <= b; i++)

typedef pair<int, int> pii;
#define mk(x, y) make_pair(x, y)
int n;
map<pii, int> mp;

inline void dfs(int x, int y, int k)
{
    if (k > 1 && mp[mk(x + 1, y)] != k - 1)
        dfs(x + 1, y, k - 1);
    if (k > 2 && mp[mk(x, y + 1)] != k - 2)
        dfs(x, y + 1, k - 2);
    if (k > 3 && mp[mk(x, y - 1)] != k - 3)
        dfs(x, y - 1, k - 3);
    if (k > 4 && mp[mk(x - 1, y)] != k - 4)
        dfs(x - 1, y, k - 4);
    mp[mk(x, y)] = k;
    cout << x << " " << y << " " << k << endl;
}

inline void solve()
{
    cin >> n;
    dfs(0, 0, n);
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
}
View Code

 

posted @ 2020-07-31 10:11  若讷  阅读(254)  评论(0编辑  收藏  举报