poj 1113 Wall

題意:國王要求建一堵牆圍繞他的城堡,且城堡與牆的距離總不小於一個數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;
}


發佈了115 篇原創文章 · 獲贊 7 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章