留下三种方法模板
以一个题为例Buried memory
1.求凸包后枚举凸包上的点。
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
//#include
using namespace std;
#define me(x,y) memset(x,y,sizeof x)
#define MIN(x,y) x < y ? x : y
#define MAX(x,y) x > y ? x : y
typedef long long ll;
typedef unsigned long long ull;
const double INF = 0x3f3f3f3f;
const double eps = 1e-08;
const double PI = acos(-1.0);
const int mod = 1e9+7;
const int maxn = 1000;
int n;
int sgn(double x){
if(fabs(x) < eps) return 0;
if(x < 0)return -1;
else return 1;
}
inline double sqr(double x){return x*x;}
struct Point{
double x,y;
Point(){}
Point(double _x,double _y){x = _x,y = _y;}
void input(){scanf("%lf%lf",&x,&y);}
void output(){printf("%.2f %.2f\n",x,y);}
bool operator == (Point b) const{return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;}
bool operator < (Point b) const{return sgn(x-b.x) == 0 ? sgn(y-b.y)<0 : x<b.x;}
Point operator -(const Point &b)const{return Point(x-b.x,y-b.y);}
double operator ^ (const Point &b)const{return x*b.y-y*b.x;} //叉积
double operator * (const Point &b)const{return x*b.x+y*b.y;} //点积
double len(){return hypot(x,y);} //返回长度
double len2(){return x*2+y*y;} //返回长度平方
double distance(Point p){return hypot(x-p.x,y-p.y);} //返回两点间距离
Point operator + (const Point &b)const{return Point(x+b.x,y+b.y);}//
Point operator * (const double &k)const{return Point(x*k,y*k);} //
Point operator / (const double &k)const{return Point(x/k,y/k);} //
double rad(Point a,Point b){Point p = *this;return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));} //计算该点看a,b点的角度
double raddifference(Point a,Point b){Point p = *this;return (a.x-p.x)*(b.y-p.y)-(b.x-p.x)*(a.y-p.y);}//a,b点相对p点的角度差
};
struct polygon{
int n;
Point p[maxn];
void input(int _n){
n = _n;
for(int i = 0; i < n; ++i) p[i].input();
}
void add(Point q){p[n++] = q;}
struct cmp{
Point p;
cmp(const Point &p0){p = p0;}
bool operator()(const Point &aa,const Point &bb){
Point a = aa,b = bb;
int d = sgn((a-p)^(b-p));
if(d == 0) return sgn(a.distance(p)-b.distance(p))<0;
return d > 0;
}
};
void norm(){ //进行极角排序,首先找到最左下角的点
Point mi = p[0];
for(int i = 1; i < n; ++i) mi = min(mi,p[i]);
sort(p,p+n,cmp(mi));
}
void getconvex(polygon &convex){ //得到凸包,内部点编号为0-n-1,如果有影响判断所有点共点或共线
sort(p,p+n);
convex.n = n;
for(int i = 0;i < min(n,2); ++i)convex.p[i] = p[i];
if(convex.n == 2 && (convex.p[0] == convex.p[1]))convex.n--;
if(n <= 2)return ;
int &top = convex.n;
top = 1;
for(int i = 2; i <n ; ++i){
while(top && sgn((convex.p[top]-p[i])^(convex.p[top-1]-p[i])) <= 0){top--;}
convex.p[++top] = p[i];
}
int temp = top;
convex.p[++top] = p[n-2];
for(int i = n-3; i >= 0; i--){
while(top != temp && sgn((convex.p[top]-p[i])^(convex.p[top-1]-p[i])) <= 0)top--;
convex.p[++top] = p[i];
}
if(convex.n == 2 && (convex.p[0] == convex.p[1]))convex.n--;
convex.norm();
}
};
Point base,rp;
int top;
double r;
polygon pol,convex;
bool cmp(Point p1,Point p2){
if(base.raddifference(p1,p2) == 0)return base.distance(p1) < base.distance(p2);
if(base.raddifference(p1,p2) > 0)return true;
else return false;
}
bool judge(double a,double b,double c){
return a*a+b*b < c*c;
}
void cal(Point p0,Point p1,Point p2){
double p0p1 = p0.distance(p1);
double p1p2 = p1.distance(p2);
double p2p0 = p0.distance(p2);
if(judge(p0p1,p1p2,p2p0) || judge(p1p2,p2p0,p0p1) || judge(p2p0,p0p1,p1p2)){
double maxlen = max(p0p1,max(p1p2,p2p0));
if(maxlen/2.0 > r){
r = maxlen/2.0;
if(maxlen == p0p1){rp.x=(p0.x+p1.x)/2.0,rp.y=(p0.y+p1.y)/2.0;}
if(maxlen == p1p2){rp.x=(p1.x+p2.x)/2.0,rp.y=(p1.y+p2.y)/2.0;}
if(maxlen == p2p0){rp.x=(p2.x+p0.x)/2.0,rp.y=(p2.y+p0.y)/2.0;}
}
}
else{
Point tmp;
double a1 = p1.x - p0.x, b1 = p1.y - p0.y, c1 = (a1 * a1 + b1 * b1) / 2.0;
double a2 = p2.x - p0.x, b2 = p2.y - p0.y, c2 = (a2 * a2 + b2 * b2) / 2.0;
double d = a1*b2-a2*b1;
tmp.x = p0.x + (c1 * b2 - c2 * b1) / d;
tmp.y = p0.y + (a1 * c2 - a2 * c1) / d;
double tmpR = p0.distance(tmp);
if(tmpR > r)rp=tmp,r=tmpR;
}
}
int main(){
while(cin>>n && n){
pol.input(n);
pol.norm();
base = pol.p[0];
if(n == 1){printf("%.2f %.2f 0.00\n",pol.p[0].x,pol.p[0].y);continue;}
pol.getconvex(convex);
if(convex.n == 2){
rp.x = (convex.p[0].x+convex.p[1].x)/2.0;
rp.y = (convex.p[0].y+convex.p[1].y)/2.0;
r = convex.p[0].distance(convex.p[1])/2.0;
printf("%.2f %.2f %.2f\n",rp.x,rp.y,r);
continue;
}
r = 0;
for(int i = 0; i < convex.n; ++i){
for(int j = i+1; j < convex.n; ++j){
for(int k = j+1; k < convex.n; ++k){
cal(convex.p[i],convex.p[j],convex.p[k]);
}
}
}
printf("%.2f %.2f %.2f\n",rp.x,rp.y,r);
}
return 0;
}
/*
*/
2.模拟退火法
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
//#include
using namespace std;
#define me(x,y) memset(x,y,sizeof x)
#define MIN(x,y) x < y ? x : y
#define MAX(x,y) x > y ? x : y
typedef long long ll;
typedef unsigned long long ull;
const double INF = 0x3f3f3f3f;
const double eps = 1e-08;
const double PI = acos(-1.0);
const int mod = 1e9+7;
const int maxn = 1000;
#define T 100
#define Delta 0.98
int n;
double r;
int sgn(double x){
if(fabs(x) < eps) return 0;
if(x < 0)return -1;
else return 1;
}
struct Point
{
double x,y;
double dis(Point b) {return sqrt((x-b.x)*(x-b.x)+(y-b.y)*(y-b.y));}
}p[550],pr;
void solve(){
double t = T;
double delta = Delta;
pr.x = pr.y= 0;
while(t > eps){
int pos = 0;
r = pr.dis(p[pos]);
for(int i = 0; i < n; ++i){
if(pr.dis(p[i]) > r){
pos = i;
r = pr.dis(p[i]);
}
}
pr.x += (p[pos].x-pr.x)/r*t;
pr.y += (p[pos].y-pr.y)/r*t;
t *= delta;
}
}
int main(){
while(cin>>n && n){
for(int i = 0; i < n; ++i) scanf("%lf%lf",&p[i].x,&p[i].y);
solve();
printf("%.2f %.2f %.2f\n",pr.x,pr.y,r);
}
return 0;
}
/*
*/
3.说了三种就是三种,但是万万没想到T掉了0.0,结果应该没问题,但还是放上来吧,三分法
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
//#include
using namespace std;
#define me(x,y) memset(x,y,sizeof x)
#define MIN(x,y) x < y ? x : y
#define MAX(x,y) x > y ? x : y
typedef long long ll;
typedef unsigned long long ull;
const double INF = 0x3f3f3f3f;
const double eps = 1e-08;
const double PI = acos(-1.0);
const int mod = 1e9+7;
const int maxn = 1000;
#define T 100
#define Delta 0.98
int n;
double r,miny,maxy,maxx,minx;
struct Point
{
double x,y;
Point(){}
Point(double _x,double _y){x=_x,y=_y;}
double dis(Point b) {return sqrt((x-b.x)*(x-b.x)+(y-b.y)*(y-b.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;}
}p[550],pr;
double cal(double x,double y){
Point ans = Point(x,y);
double res = 0;
for(int i = 0; i < n; ++i) res = max(res,ans.dis(p[i]));
return res;
}
double three_search2(double x){
double l = miny,r = maxy;
while(r-l > eps){
double lmid = l+(r-l)/3;
double rmid = r-(r-l)/3;
if(cal(x,lmid) >= cal(x,rmid)) l = lmid;
else r = rmid;
}
return l;
}
Point three_search(){
double l = minx,r = maxx;
while(r-l > eps){
double lmid = l+(r-l)/3;
double rmid = r-(r-l)/3;
if(cal(lmid,three_search2(lmid)) >= cal(rmid,three_search2(rmid))) l = lmid;
else r = rmid;
}
return Point(l,three_search2(l));
}
int main(){
while(cin>>n && n){
minx = miny = INF;
maxx = maxy = -INF;
for(int i = 0; i < n; ++i) {
scanf("%lf%lf",&p[i].x,&p[i].y);
minx = MIN(p[i].x,minx),miny = MIN(p[i].y,miny);
maxx = MAX(maxx,p[i].x),maxy = MAX(maxy,p[i].y);
}
pr = three_search();
r = cal(pr.x,pr.y);
printf("%.2f %.2f %.2f\n",pr.x,pr.y,r);
}
return 0;
}
/*
*/