2017 United Kingdom and Ireland Programming(Gym

题目很水。睡过了迟到了一个小时,到达战场一看,俩队友AC五个了。。

就只贴我补的几个吧。

B - Breaking Biscuits Gym - 101606B

旋转卡壳模板题。然后敲错了。

代码是另一种做法:对于每条边,枚举两边的所有点到直线的距离,分别取最大值,然后加起来。

#include <bits/stdc++.h>
#define FOPI freopen("in.txt", "r", stdin);
#define FOPO freopen("out.txt", "w", stdout);
using namespace std;
typedef long long LL;
const double esp = 1e-8;
const int maxn = 100 + 10;

struct Point
{
    double x, y;
    Point() {}
    Point(double _x, double _y) { x = _x, y = _y; }
    Point operator - (const Point &b) const
    {
        return Point(x-b.x, y-b.y);
    }
    double operator * (const Point &b) const
    {
        return x*b.x + y*b.y;
    }
    double length() { return hypot(x, y); }
};
typedef Point Vector;

double cross(Vector a, Vector b) { return a.x*b.y - a.y*b.x; }
double dist(Point p, Point a, Point b)
{
    return cross(p-a, b-a) / (b-a).length();
}

Point a[maxn];
int n;
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%lf%lf", &a[i].x, &a[i].y);

    double ans = 1e50;
    for (int i = 1; i <= n; i++)
        for (int j = i+1; j <= n; j++)
        {
            double left = 1e50, right = -1e50;
            for (int k = 1; k <= n; k++)
            {
                left = min(left, dist(a[k], a[i], a[j]));
                right = max(right, dist(a[k], a[i], a[j]));
            }
            ans = min(ans, right-left);
        }

    printf("%.7f
", ans);
}

F - Flipping Coins Gym - 101606F

dp[i][j] 表示 翻了 j 次后,有 i 个正面朝上的概率。

每次翻面一定优先翻反面朝上的硬币。

那么dp[i][j]的概率可以更新 dp[i+1][j+1] 和 dp[i]j+1]。

特别的,对于 i == n, dp[i][j] 更新的是dp[i-1][j+1] 和 dp[i][j+1]

#include <bits/stdc++.h>
using namespace std;
const int maxn = 400 + 100;

int n, k;
double dp[maxn][maxn];

int main()
{
    scanf("%d%d", &n, &k);

    dp[0][0] = 1;
    for (int j = 0; j < k; j++)
    for (int i = 0; i <= n; i++)
    {
        if (i == n)
        {
            dp[i-1][j+1] += 0.5*dp[i][j];
            dp[i][j+1] += 0.5*dp[i][j];
        }
        else
        {
            dp[i+1][j+1] += 0.5*dp[i][j];
            dp[i][j+1] += 0.5*dp[i][j];
        }
    }

    double ans = 0;
    for (int i = 0; i <= n; i++) ans += dp[i][k] * i;

    printf("%.7f
", ans);
}

L - Lizard Lounge Gym - 101606L

对于每一个人求出他和中点的斜率来,然后约分后分类,分别求LIS。

WA了一次是因为求成最长不降升子序列了。估计场上急眼了的话不好查错。

pair还是很好用的。

#include <bits/stdc++.h>
#define FOPI freopen("in.txt", "r", stdin);
#define FOPO freopen("out.txt", "w", stdout);
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 100;
typedef pair<int, int> prInt;
typedef pair<double, int> prDouble;

int sx, sy;
int n;
int x[maxn], y[maxn];
int k[maxn];
map<prInt, int> M;
vector<prDouble> a[maxn];

int LIS(vector<prDouble> &a)
{
    int tot = 0;
    for (int i = 0; i < a.size(); i++)
    {
        int l = 1, r = tot, x = -1;
        while(l <= r)
        {
            int mid = (l+r)/2;
            if (k[mid] >= a[i].second) x = mid, r = mid-1;
            else l = mid+1;
        }
        if (x == -1) x = ++tot;
        k[x] = a[i].second;
    }
    return tot;
}

int main()
{
    scanf("%d%d", &sx, &sy);
    scanf("%d", &n);
    int cnt = 0;
    for (int i = 1; i <= n; i++)
    {
        int x, y, h;
        scanf("%d%d%d", &x, &y, &h);
        x -= sx, y -= sy;
        int g = __gcd(abs(x), abs(y));
        prInt p = prInt(x/g, y/g);
        if (!M.count(p)) M[p] = ++cnt;
        a[M[p]].push_back(prDouble(hypot(x, y), h));
    }

    int ans = 0;
    for (int i = 1; i <= cnt; i++)
    {
        sort(a[i].begin(), a[i].end());
        ans += LIS(a[i]);
    }
    printf("%d
", ans);
}
原文地址:https://www.cnblogs.com/ruthank/p/10653086.html