1. 程式人生 > >HDU - 6080 :度度熊保護村莊 (凸包,floyd最小環)(VJ1900題達成)

HDU - 6080 :度度熊保護村莊 (凸包,floyd最小環)(VJ1900題達成)

pri div -a pac for main 之間 ret !=

pro:二維平面上,給定N個村莊。M個士兵駐守,把村莊圍住,現在我們想留下更多的士兵休息,使得剩下的士兵任然滿足圍住村莊。N,M<500;

sol:即是要找一個最小的環,環把村莊圍住。 由於是環, 最小的點數等價於最小的邊數。 所以我們求最小的邊數,而士兵之間能有有向邊,當且僅當所有的村莊在有向邊的左邊(逆時針連邊)。 然後就是floyd最小環。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const
int maxn=510; const int inf=1e9; const double pi=acos(-1.0); struct point{ int x,y; point(){} point(int xx,int yy):x(xx),y(yy){} }a[maxn],b[maxn]; ll det(point a,point b){ return a.x*b.y-a.y*b.x;} ll dot(point a,point b){ return a.x*b.x+a.y*b.y;} point operator +(point a,point b){ return
point(a.x+b.x,a.y+b.y);} point operator -(point a,point b){ return point(a.x-b.x,a.y-b.y);} int dis[maxn][maxn]; int main() { int N,M,ans; while(~scanf("%d",&N)){ rep(i,1,N) scanf("%d%d",&a[i].x,&a[i].y); scanf("%d",&M); rep(i,1,M) scanf("%d%d
",&b[i].x,&b[i].y); rep(i,1,M) rep(j,1,M) dis[i][j]=inf; ans=inf; rep(i,1,M) rep(j,1,M){ if(i==j) continue; bool F=1; rep(k,1,N){ if(det(b[j]-b[i],a[k]-b[i])<0){ F=0; break; } } if(F) dis[i][j]=1; } rep(k,1,M) rep(i,1,M) if(dis[i][k]!=inf) //刪去後很慢 rep(j,1,M) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); rep(i,1,M) ans=min(ans,dis[i][i]); if(ans==inf) puts("ToT"); else printf("%d\n",M-ans); } return 0; }

HDU - 6080 :度度熊保護村莊 (凸包,floyd最小環)(VJ1900題達成)