題意:國王要求建一堵牆圍繞他的城堡,且城堡與牆的距離總不小於一個數L,要求求最小的牆壁周長。
分析:直接求出凸包然後加上半徑爲L的圓的周長,對於證明卻有點不太理解~。用捲包裹發求出凸包上的點,然後算出凸包的周長,加上圓的周長即爲所求。
PS:我的程序不能求出凸包上所有的點,對於共線的情況只能取最遠的一點,還沒想到一個好辦法解決。
以下附上代碼:
#include <algorithm>
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cctype>
#include <cmath>
#include <stack>
#include <queue>
#include <list>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pi = acos(-1.0);
const int maxn = 1005;
struct Point{
int x,y;
Point(){}
Point(int x_, int y_) :
x(x_), y(y_) {}
bool operator < (const Point b) const{
if(y != b.y) return y < b.y;
return x < b.x;
}
bool operator != (const Point b) const{
return x != b.x || y != b.y;
}
bool operator == (const Point b) const{
return x == b.x && y == b.y;
}
Point operator - (const Point b) const{
Point t(x-b.x,y-b.y);
return t;
}
int operator * (const Point b) const{
return x*b.x + y*b.y;
}
int operator ^ (const Point b) const{
return x*b.y - y*b.x;
}
int len2(){
return x*x+y*y;
}
};
int n,l;
Point x[maxn];
int ans[maxn];
int cnt;
void input()
{
for(int i = 0; i < n; i++){
scanf("%d%d",&x[i].x,&x[i].y);
}
}
void solve()
{
sort(x,x+n);
cnt = 0;
ans[cnt++] = 0;
Point v1,v2;//vector
int index;
while(cnt == 1 || ans[cnt-1] != 0){
for(int i = n-1; i >= 0; i--){
if(i == ans[cnt-1]) continue;
v1 = x[i] - x[ans[cnt-1]];
index = i;
break;
}
for(int i = 0; i < n; i++){
if(i == ans[cnt-1] || i == index) continue;
v2 = x[i] - x[ans[cnt-1]];
if((v1^v2) < 0){
v1 = v2;
index = i;
}
else if((v1^v2) == 0 && v1.len2() < v2.len2()){
v1 = v2;
index = i;
}
}
ans[cnt++] = index;
}//end of while
Point v;
double sum = 0.0;
for(int i = 1; i < cnt; i++){
v = x[ans[i]] - x[ans[i-1]];
sum += sqrt(1.0*v.len2());
}
double res = sum;
res += 2 * pi * l;
printf("%.0lf\n",res);
}
int main()
{
while(scanf("%d%d",&n,&l) != EOF){
input();
solve();
}
return 0;
}
Graham:
#include <algorithm>
#include <iostream>
#include <sstream>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cctype>
#include <cmath>
#include <stack>
#include <queue>
#include <list>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pi = acos(-1.0);
const int maxn = 1005;
struct Point{
int x,y;
Point(){}
Point(int x_, int y_) :
x(x_), y(y_) {}
//point
bool operator < (const Point &b) const{
if(x != b.x) return x < b.x;
return y < b.y;
}
Point operator - (const Point &b) const{
Point t(x-b.x,y-b.y);
return t;
}
//vector
int operator ^ (const Point &b) const{
return x*b.y - y*b.x;
}
int len2(){
return x*x + y*y;
}
};
int n,l;
Point p[maxn];
int res[maxn];
int cnt;
void input()
{
for(int i = 0; i < n; i++){
scanf("%d%d",&p[i].x,&p[i].y);
}
}
bool cmp(Point a, Point b)
{
Point v1 = a - p[0];
Point v2 = b - p[0];
if((v1 ^ v2) != 0) return (v1 ^ v2) > 0;
return v1.len2() < v2.len2();
}
void Graham()
{
cnt = 0;
sort(p,p+n);
sort(p+1,p+n,cmp);
if(n == 0) return; res[cnt++] = 0;
if(n == 1) return; res[cnt++] = 1;
if(n == 2) return;
Point v1,v2;
for(int i = 2; i < n; i++){
while(cnt){
v1 = p[res[cnt-1]] - p[res[cnt-2]];
v2 = p[i] - p[res[cnt-1]];
if((v1 ^ v2) >= 0) break;
--cnt;
}
res[cnt++] = i;
}
}
void solve()
{
Graham();
double ans = 0.0;
Point v;
for(int i = 1; i < cnt; i++){
v = p[res[i]] - p[res[i-1]];
ans += sqrt(1.0*v.len2());
}
v = p[0] - p[res[cnt-1]];
ans += sqrt(1.0*v.len2());
ans += 2 * pi * l;
printf("%.0lf\n",ans);
}
int main()
{
while(scanf("%d%d",&n,&l) != EOF){
input();
solve();
}
return 0;
}