ZOJ3537 解題報告及總結

題目意思就是 給你一個多邊形,先判斷是否是凸包,然後再劃分成一個一個三角形,求最小代價,兩點之間畫一條線的最小代價爲 abs(xi + xj) * abs(yi + yj) % p


才做的時候,想法是枚舉劃分的線,根據分治的思想,大的多邊形拆成兩個小多邊形,然後記憶化,複雜度超高難寫不說(因爲要記錄i節點的nxt節點編號,不停地變來變去),還不知道wa在哪。。
後來想了下,既然最後一定是一個一個的三角形,那麼多邊形的一條邊肯定是三角形的邊,那麼挨着的兩個點,一定在一個三角形內,那麼只需要枚舉第三個定點,複雜度降低一維,而且很好寫
//
//  Created by Running Photon on 2016-02-25
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <set>
#include <vector>
#include <stack>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const double eps = 1e-9;

struct Point {
    ll x, y;
    Point(ll _x = 0, ll _y = 0) : x(_x), y(_y) {}
    void read() {
        scanf("%lld%lld", &x, &y);
    }
    bool operator< (const Point rhs) const {
        if(x == rhs.x) return y < rhs.y;
        return x < rhs.x;
    }
    void print() {
        printf("%lld  %lld\n", x, y);
    }
    Point operator+ (Point rhs) {
        return Point(x + rhs.x, y + rhs.y);
    }
    Point operator- (Point rhs) {
        return Point(x - rhs.x, y - rhs.y);
    }
    Point operator* (ll rhs) {
        return Point(x * rhs, y * rhs);
    }
    Point operator/ (ll rhs) {
        return Point(x / rhs, y / rhs);
    }
    ll operator* (Point rhs) {
        return x * rhs.x + y * rhs.y;
    }
    ll operator^ (Point rhs) {
        return x * rhs.y - y * rhs.x;
    }
};
vector <Point> Gh(vector <Point>& a) {
    vector <Point> res;
    int m = 0;
    sort(ALL(a));
    if(a.size() <= 2) {
        for(int i = 0; i < a.size(); i++) {
            res.push_back(a[i]);
        }
        res.push_back(a[0]);
    }
    for(int i = 0; i < a.size(); i++) {
        while(m > 1 && ((res[m-1] - res[m-2]) ^ (a[i] - res[m-2])) <= 0) {
            m--;
            res.pop_back();
        }
        m++;
        res.push_back(a[i]);
    }
    int k = m;
    for(int i = a.size() - 2; i >= 0; i--) {
        while(m > k && ((res[m-1] - res[m-2]) ^ (a[i] - res[m-2])) <= 0) {
            m--;
            res.pop_back();
        }
        m++;
        res.push_back(a[i]);
    }
    res.pop_back();
    return res;
}
vector <Point> gh;
int n;
ll p;
ll calc(Point l, Point r) {
    return abs(l.x + r.x) * abs(l.y + r.y) % p;
}
ll cost[305][305];
ll dp[305][305];
int nxt[305];
ll dfs(int l, int r) {
    if(r - l <= 2) return 0;
    if(dp[l][r] != -1) return dp[l][r];
    ll& ret = dp[l][r];
    ret = inf;
    for(int i = l + 1; i < r; i++) {
        ret = min(ret, dfs(l, i) + dfs(i, r) + cost[i][l] + cost[i][r]);
    }
    return ret;
}
int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);

    while(scanf("%d%lld", &n, &p) != EOF) {
        memset(dp, -1, sizeof dp);
        CLR(cost);
        gh.clear();
        vector <Point> g;
        for(int i = 0; i < n; i++) {
            ll x, y;
            scanf("%lld%lld", &x, &y);
            g.push_back(Point(x, y));
        }
        vector <Point> gh = Gh(g);
        for(int i = 0; i < gh.size(); i++) {
            for(int j = i + 2; j < gh.size(); j++) {
                cost[j][i] = cost[i][j] = calc(gh[i], gh[j]);
            }
        }
//        printf("%d\n", gh.size());
//        for(int i = 0; i < gh.size(); i++) {
//            gh[i].print();
//        }
        if(gh.size() != g.size()) {
            puts("I can't cut.");
            continue;
        }
        printf("%lld\n", dfs(0, gh.size() - 1));
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章