您的位置:首页 > 其它

ZOJ3537 解题报告及总结

2016-02-25 20:01 295 查看
题目意思就是 给你一个多边形,先判断是否是凸包,然后再划分成一个一个三角形,求最小代价,两点之间画一条线的最小代价为 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: