poj3178 Roping the Field (计算几何 + dp)

Roping the Field

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 858   Accepted: 250

Description

Farmer John is quite the nature artist: he often constructs large works of art on his farm. Today, FJ wants to construct a giant "field web". FJ‘s field is large convex polygon with fences along the boundary and fence posts at each of the N corners (1 <= N <= 150). To construct his field web, FJ wants to run as many ropes as possible in straight lines between pairs of non-adjacent fence posts such that no two ropes cross.

There is one complication: FJ‘s field is not completely usable. Some evil aliens have created a total of G (0 <= G <= 100) grain circles in the field, all of radius R (1 <= R <= 100,000). FJ is afraid to upset the aliens, and therefore doesn‘t want the ropes to pass through, or even touch the very edge of a grain circle. Note that although the centers of all the circles are contained within the field, a wide radius may make it extend outside of the field, and both fences and fence posts may be within a grain circle.

Given the locations of the fence posts and the centers of the circles, determine the maximum number of ropes that FJ can use to create his field web.

FJ‘s fence pots and the circle centers all have integer coordinates X and Y each of which is in the range 0..1,000,000.

Input

Line 1: Three space-separated integers: N, G, and R

Lines 2..N+1: Each line contains two space-separated integers that are the X,Y position of a fence post on the boundary of FJ‘s field.

Lines N+2..N+G+1: Each line contains two space-separated integers that are the X,Y position of a circle‘s center inside FJ‘s field.

Output

Line 1: A single integer that is the largest number of ropes FJ can use for his artistic creation.

Sample Input

5 3 1
6 10
10 7
9 1
2 0
0 3
2 2
5 6
8 3

Sample Output

1

Hint

Explanation of the sample:

A pentagonal field, in which all possible ropes are blocked by three grain circles, except for the rope between fenceposts 2 and 4.

题意:

在一平面上,按顺序给定 n 个点(事实上给出的点可以按顺逆时针围成一个闭合的多边形),m 个半径为 r 的圆。要给 n 个点两两连线,要求最多能连多少条线;

连线限制:

  1. 连线不能穿过任意一个圆,也不能与圆相切;
  2. 连线不能在中途相交,同一个点可以连多条线;
  3. 相邻的两个点不能连线(第一个点和第 n 个点是相邻的)。

思路:

首先在不考虑相交的情况下预处理出哪两个点可以连线,然后dp;

dp[i][j] 表示第 i 个点到第 j 个点最多可连多少条线,dp[i][j] = max(dp[i][k] + dp[k][j] + cnc[i][j], dp[i][j]);

其中 i < k < j;cnc[i][j] 表示 i , j 能否连线,能则为1,否则为0;

代码:

#include<map>
#include<set>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<cctype>
#include<cfloat>
#include<cstdio>
#include<memory>
#include<string>
#include<vector>
#include<cassert>
#include<csignal>
#include<cstdlib>
#include<cstring>
#include<numeric>
#include<utility>
#include<iostream>
#include<algorithm>
#include<functional>
#define LL long long
#define PB push_back
#define MAXN 171
#define RPT(I,L,R) for(int I=L;I<R;++I)
#define TPR(I,R,L) for(int I=R;I>=L;--I)
using namespace std;
template<class T> bool Umx(T &A,const T &B)
{
    return B>A?A=B,1:0;
}
template<class T> bool Umn(T &A,const T &B)
{
    return B<A?A=B,1:0;
}
const int inf=~0u>>2;

int n,m,i,j,k;
LL r;
bool cnc[MAXN][MAXN];
int f[MAXN][MAXN];

struct point
{
    LL x,y;
    bool operator < (const point &T) const
    {
        return this->y<T.y || (this->y==T.y && this->x<T.x);
    }
    void read()
    {
        scanf("%I64d%I64d",&x,&y);
    }
} p[MAXN],c[MAXN];

inline LL sqr(LL X)
{
    return X*X;
}
inline LL dot(point A,point B,point O)
{
    return (A.x-O.x)*(B.x-O.x)+(A.y-O.y)*(B.y-O.y);
}
inline LL cross(point A,point B)
{
    return A.x*B.y-B.x*A.y;
}
inline LL cross(point A,point B,point O)
{
    return (A.x-O.x)*(B.y-O.y)-(B.x-O.x)*(A.y-O.y);
}
inline LL dist2(point A,point B)
{
    return sqr(A.x-B.x)+sqr(A.y-B.y);
}

struct cmp
{
    point O;
    cmp(const point &OO):O(OO) {}
    bool operator()(const point &A,const point &B)
    {
        return cross(A,B,O)>0;
    }
};

void init()
{
    memset(f,-1,sizeof f);
    scanf("%d%d%d",&n,&m,&r);
    RPT(i,0,n) p[i].read();
    RPT(i,0,m) c[i].read();
    sort(p,p+n);
    sort(p+1,p+n,cmp(p[0]));
}

bool CrsCcl(point A,point B,point O)
{
    if (sqr(r)>=min(dist2(O,A),dist2(O,B))) return true;
    if (dot(B,O,A)<0ll || dot(A,O,B)<0ll) return false;
    return (double)r*r*dist2(A,B)>=(double)cross(A,B,O)*cross(A,B,O);
}

void Deal_Cnc()
{
    memset(cnc,false,sizeof cnc);
    RPT(i,0,n)
    RPT(j,i+2,n)
    if (!(i==0 && j==n-1))
    {
        cnc[i][j]=cnc[j][i]=true;
        RPT(k,0,n)
        if (CrsCcl(p[i],p[j],c[k]))
        {
            cnc[i][j]=cnc[j][i]=false;
            break;
        }
    }
}

int DP(int L,int R)
{
    if (f[L][R]>0) return f[L][R];
    if (R-L<2) return f[L][R]=0;
    else if (R-L==2) return cnc[L][R];
    int res=0;
    RPT(i,L+1,R) Umx(res,DP(L,i)+DP(i,R));
    return f[L][R]=res+cnc[L][R];
}

int main()
{
    init();
    Deal_Cnc();
    printf("%d\n",DP(0,n-1));
    return 0;
}
时间: 2024-10-23 02:37:54

poj3178 Roping the Field (计算几何 + dp)的相关文章

POJ3178 计算几何+DP

1 //一些点一些圆,过圆不能连线,相邻点不能连线,问最多连几条线 2 //计算几何模板+区间dp 3 //关键是判断圆和线段是否相交 4 #include <cstdio> 5 #include <cmath> 6 #include <algorithm> 7 #define N 500 8 #define ll long long 9 #define sqr(x) ((x)*(x)) 10 using namespace std; 11 bool ok[N][N];

Code Chef MINPOLY(计算几何+dp)

题面 传送门 题解 我们枚举这个凸多边形\(y\)坐标最小的点\(p_i\),然后对于所有\(y\)坐标大于等于它的点极角排序 我们预处理出\(s_{j,k}\)表示三角形\(p_i,p_j,p_k\)内部的点的\(b\)总和(不包括边界),然后记\(dp_{i,j,k}\)表示这个凸多边形之前两个点是\(p_i,p_j\),还需要\(k\)个点,最小的\(b\)是多少,然后可以直接记忆化搜索 //minamoto #include<bits/stdc++.h> #define R regis

bzoj 3778: 共鸣【计算几何+dp】

枚举起点,然后设f[i][j]为上凸壳上一个点是i当前点是j的最大面积,g是下凸壳,然后合并的时候枚举结束点t合并上下凸壳即可 这样的好处是每次转移都是往凸多边形里加一个三角形(s,i,j),所以判断转移合法只要预处理出所有三角形是否合法即可,同时预处理出三角形面积,转移就是f[j][k]=max(f[j][k],f[i][j]+c[s][j][k]); #include<iostream> #include<cstdio> #include<algorithm> #i

POJ 3254 Corn Field ( 状态压缩DP )

简单题,边界处理注意.可以优化,就不精益求精了. #include <iostream> #include <cstring> #include <vector> #include <fstream> using namespace std; #define MOD 100000000 int field[20]; int DP[20][1200]; int main(){ int N, M; cin >> N >> M; memse

POJ 3254 Corn Fields 状压DP

链接:http://poj.org/problem?id=3254 题意:一块M*N的田地,每小块地大小是1*1,可以种植物的标记为1,不可以种植物的标记为0,并且相邻的两块地不可以同时种植物.问题是有多少种不同的种植方案(所有地都不种也是一种种植方案) 思路:这是第一道状压DP题,从第一行更新到最后一行,每一行用一个N位的二进制数来表示该行的状态1表示该位置种了植物,0表示该位置没种植物.因为每块地只对相邻的土地能否种植有所影响,所以每一行的状态可以用前一行的状态递推得到. 资料:http:/

【转】[专题学习][计算几何]

原文地址:http://www.cnblogs.com/ch3656468/archive/2011/03/02/1969303.html 基本的叉积.点积和凸包等东西就不多说什么了,网上一搜一大堆,切一些题目基本熟悉了就差不多了. 一些基本的题目可以自己搜索,比如这个blog:http://blog.sina.com.cn/s/blog_49c5866c0100f3om.html 接下来,研究了半平面交,思想方法看07年朱泽园的国家队论文,模板代码参考自我校大牛韬哥: http://www.o

hdu 1081 dp问题:最大子矩阵和

题目链接 题意:给你一个n*n矩阵,求这个矩阵的最大子矩阵和 #include<iostream> #include<cstdio> #include<string.h> using namespace std; #define inf -0x3f3f3f3f int field[105][105],dp[105]; int main() { int n; while(~scanf("%d",&n)) { int maxn=0; memset

杭电ACM分类

杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDIATE DECODABILITY

【转】对于杭电OJ题目的分类

[好像博客园不能直接转载,所以我复制过来了..] 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDI