给组数,给边数给一个点,
给一堆边。
求包围的最小周长。
思路清晰,每条边只加一次,为逆时针缠绕。
然后化边为点,边到边如果左旋就有一个初始距离,然后求floyed。
lightoj 的>>不能连着写,不然就会挂。
#include <cstdio> #include <iostream> #include <cstdlib> #include <algorithm> #include <cstring> #include <stack> #include <cmath> #include <map> #include <vector> using namespace std; typedef pair<int,int> Point; struct Edge { Point rro,to; double dis; }; map< Point , vector <int> > PE; Edge e[110]; int isLeft(Point a,Point b,Point c) { return (c.first-a.first)*(b.second-a.second)-(c.second-a.second)*(b.first-a.first)<=0; } double Dis(Point a,Point b) { return sqrt((b.first-a.first)*(b.first-a.first)+(b.second-a.second)*(b.second-a.second)); } double dp[110][110]; int main() { int T,n,ncas=1; scanf ("%d",&T); while (T--) { PE.clear(); Point BULL; scanf ("%d%d%d",&n,&BULL.first,&BULL.second); for (int i=0;i<n;i++) { scanf ("%d%d%d%d",&e[i].rro.first,&e[i].rro.second,&e[i].to.first,&e[i].to.second); if (!isLeft(e[i].rro,e[i].to,BULL))swap(e[i].rro,e[i].to); e[i].dis=Dis(e[i].rro,e[i].to); // printf ("(%f,%f),(%f,%f)\n",e[i].rro.x,e[i].rro.y,e[i].to.x,e[i].to.y); // printf ("%f\n",e[i].dis); PE[e[i].rro].push_back(i); } for (int i=0;i<110;i++) { for (int j=0;j<110;j++) { dp[i][j]=0x7f7f7f7f; } } for (int u=0;u<n;u++) { for (int v=0;v<PE[e[u].to].size();v++) { int bian=PE[e[u].to][v]; if (isLeft(e[u].rro,e[u].to,e[bian].to)) { // printf ("YES\n"); dp[u][bian]=e[u].dis+e[bian].dis; } } } for (int k=0;k<n;k++) { for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { dp[i][j]=min(dp[i][k]+dp[k][j],dp[i][j]); } } } double ans=0x7f7f7f7f; for (int i=0;i<n;i++) ans=min(ans,dp[i][i]); if (fabs(ans-0x7f7f7f7f)<1e-9) { printf ("Case %d: -1.000\n",ncas++); } else printf ("Case %d: %.10f\n",ncas++,ans); } return 0; }
时间: 2024-10-11 22:24:43