2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02)

B Bricks 计算几何乱搞

题意:

给你个立方体,问你能不能放进一个管道里面。

题解:

这是一道非常迷的题,其问题在于,你可以不正着放下去,你需要斜着放。此时你需要枚举你旋转的角度,来判断是否可行。至于枚举的范围和步长,看脸乱搞。

代码:

//#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<fstream>
using namespace std;

long double x[3],y[2];

const long double pi=acos(-1);

long double a,b;
long double d,e;

const long double eps=1e-5;

int main() {
    ifstream cin("bricks.in");
    ofstream cout("bricks.out");
    cin.sync_with_stdio(false);
    cin >> x[0] >> x[1] >> x[2] >> y[0] >> y[1];
    sort(x, x + 3);
    sort(y, y + 2);
    a = x[0], b = x[1];
    d = y[0], e = y[1];
    if (d - a > -eps && e - b > -eps) {
        cout << "YES" << endl;
        return 0;
    }
    long double dd = pi / (2 * (3e6));
    for (long double t = acos(e / b); t < asin(d / b) + dd; t += dd) {
        if (min((e - b * cos(t)) / sin(t), (d - b * sin(t)) / cos(t)) > a - eps) {
            cout << "YES" << endl;
            return 0;
        }
    }
    cout << "NO" << endl;
    return 0;
}
View Code

E Evacuation Plan 最小费用流

题意:

题目好长好长好长。。。。。简单说就是,发生核战争了,人们要避难,给你每个建筑的坐标,给你每个避难所的坐标,每个建筑里面有若干人,从一个建筑到一个避难所的时间,是坐标的曼哈顿距离,现在要你使总时间花费最少。

题解:

就最小费用的模板题。最后在残余网络上寻找解即可。

代码:

//#include <iostream>
#include<vector>
#include<fstream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<string>
#include<cmath>
#define MAX_V 222
#define INF 1008611
using namespace std;
struct edge {
public:
    int to, cap, cost, rev;
    bool isRev;

    edge(int t, int c, int co, int re,bool ir) : to(t), cap(c), cost(co), rev(re),isRev(ir) { }

    edge() { }
};
int V=0;
vector<edge> G[MAX_V];
int dist[MAX_V];
int prevv[MAX_V],preve[MAX_V];

void add_edge(int from,int to,int cap,int cost) {
    G[from].push_back(edge(to,cap,cost,G[to].size(),0));
    G[to].push_back(edge(from,0,-cost,G[from].size()-1,1));
}

char cc;
int min_cost_flow(int s,int t,int f) {
    int res = 0;
    while (f > 0) {
        fill(dist, dist + V, INF);
        dist[s] = 0;
        bool update = 1;
        while (update) {
            update = 0;
            for (int v = 0; v < V; v++) {
                if (dist[v] == INF)continue;
                for (int i = 0; i < G[v].size(); i++) {
                    edge &e = G[v][i];
                    if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
                        //cout<<"*"<<endl;
                        dist[e.to] = dist[v] + e.cost;
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        update = 1;
                    }
                }
            }
        }
        if (dist[t] == INF)
            return -1;

        int d = f;
        for (int v = t; v != s; v = prevv[v])
            d = min(d, G[prevv[v]][preve[v]].cap);
        f -= d;
        res += d * dist[t];
        for (int v = t; v != s; v = prevv[v]) {
            edge &e = G[prevv[v]][preve[v]];
            e.cap -= d;
            G[v][e.rev].cap += d;
        }
    }
    return res;
}

int n,m;

struct build {
public:
    int x, y,c;

    build(int xx, int yy,int cc) : x(xx), y(yy), c(cc){ }

    build() { }

    int dis(build a){
        return abs(a.x-x)+abs(a.y-y)+1;
    }
};

typedef build shelter;

build bu[MAX_V];
shelter sh[MAX_V];

int plan;
int S=0;

int main() {
    ifstream cin("evacuate.in");
    ofstream cout("evacuate.out");
    cin.sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> bu[i].x >> bu[i].y >> bu[i].c;
        S += bu[i].c;
    }
    for (int i = 0; i < m; i++)
        cin >> sh[i].x >> sh[i].y >> sh[i].c;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++) {
            int k;
            cin >> k;
            plan += k * bu[i].dis(sh[j]);
        }
    for (int i = 0; i < n; i++)
        add_edge(n + m, i, bu[i].c, 0);
    for (int j = 0; j < m; j++)
        add_edge(j + n, n + m + 1, sh[j].c, 0);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            add_edge(i, j + n, INF, bu[i].dis(sh[j]));
    V = n + m + 2;
    int tmp = min_cost_flow(n + m, n + m + 1, S);
    if (tmp == plan) {
        cout << "OPTIMAL" << endl;
        return 0;
    }
    cout << "SUBOPTIMAL" << endl;
    for (int i = 0; i < n; i++, cout << endl)
        for (int j = 0; j < G[i].size(); j++)
            if (!G[i][j].isRev)
                cout << INF - G[i][j].cap << " ";

    return 0;
}
View Code

I Inlay Cutters 模拟+图论

题意:

给你一个棋盘,现在切若干刀,问你最后有几个三角形。

题解:

由于三个点在平面上只能构成三角形,那么此题可以转化为图论问题来解决,将相邻的直线交点连边,然后在图上求有多少个三元环即可。

代码:

//#include<iostream>
#include<fstream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cmath>
#define MAX_N 10004
using namespace std;

int N,M,K;

int d[4];

struct knife {
public:
    int from, to, dir;

    knife(int f, int t, int d) : from(f), to(t), dir(d) { }

    knife() { }
};

knife kn[MAX_N];

int cnt[MAX_N];

vector<int> G[MAX_N];

int main() {
    ifstream cin("inlay.in");
    ofstream cout("inlay.out");
    cin.sync_with_stdio(false);
    cin >> M >> N >> K;
    d[0] = 2 * M + 1;
    d[1] = 1;
    d[2] = M + 1;
    d[3] = M;
    for (int i = 0; i < K; i++) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        if (y1 > y2 || (y1 == y2 && x1 > x2)) {
            swap(x1, x2);
            swap(y1, y2);
        }
        int u = x1 * d[1] + y1 * d[0];
        int v = x2 * d[1] + y2 * d[0];
        int t;
        if (x1 == x2)t = 0;
        else if (y1 == y2)t = 1;
        else if (x2 > x1)t = 2;
        else t = 3;
        kn[i] = knife(u, v, t);
    }
    kn[K++] = knife(0, M, 1);
    kn[K++] = knife(N * d[0], N * d[0] + M * d[1], 1);
    kn[K++] = knife(0, N * d[0], 0);
    kn[K++] = knife(M, N * d[0] + M, 0);
    for (int i = 0; i < K; i++) {
        int u = kn[i].from, v = kn[i].to, t = kn[i].dir;
        while (u != v) {
            cnt[u]++;
            u += d[t];
        }
        cnt[v]++;
    }
    int V = -1;
    for (int i = 0; i < K; i++) {
        int u = kn[i].from, v = kn[i].to, t = kn[i].dir;
        int p = u;
        while (u != v) {
            u += d[t];
            if (cnt[u] > 1) {
                V = max(V, u);
                V = max(V, p);
                G[p].push_back(u);
                G[u].push_back(p);
                p = u;
            }
        }
    }
    int ans = 0;
    V++;
    for (int u = 0; u < V; u++)
        sort(G[u].begin(), G[u].end());
    for (int u = 0; u < V; u++)
        for (auto v:G[u])
            for (auto c:G[v]) {
                if (c == u)continue;
                int t = lower_bound(G[c].begin(), G[c].end(), u) - G[c].begin();
                if (G[c][t] == u)ans++;
                //cout<<c<<" "<<u<<" "<<v<<endl;
            }
    cout << ans/6 << endl;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/HarryGuo2012/p/4782582.html