bz1027 [JSOI2007]合金
由于本人傻×,给bzoj上贡献了满满一屏的wa,真是对不住了......
这个题其实挺水的,我就简单一说吧。可以看出选的原材料组成的凸包一定要包住需求的材料组成的凸包,那么我们枚举任意两个材料的点,如果他们的向量在所有材料组成的点的同侧的话,就给这两个点连一条1的边,否则连一条正无穷的边,那么用floyd跑一边最小环 就行了。注意特殊情况,如果只有1个点就能满足,那么这个点必须和所有需求的点重合,如果只有2个点就能满足,那么所有需求的点都应在这两个点的连线段上。
metal
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define maxn 1000 7 #define inf 100000000 8 #define eps 1e-9 9 using namespace std; 10 struct point 11 { 12 double x,y; 13 friend point operator -(const point &a,const point &b) 14 { 15 point tmp; 16 tmp.x=a.x-b.x; tmp.y=a.y-b.y; 17 return tmp; 18 } 19 friend double operator *(const point &a,const point &b) 20 { 21 return a.x*b.y-a.y*b.x; 22 } 23 }a[maxn],b[maxn]; 24 double z; 25 int n,m,ans; 26 int f[maxn][maxn],d[maxn][maxn]; 27 28 double fabs(double a) 29 { 30 return a>0?a:-a; 31 } 32 33 bool judge(int i,int j) 34 { 35 for (int k=1;k<=n;k++) 36 if (((a[j]-a[i])*(b[k]-a[j]))<-eps) return 0; 37 return 1; 38 } 39 40 bool single(int i) 41 { 42 for (int k=1;k<=n;k++) 43 if (a[i].x!=b[k].x||a[i].y!=b[k].y) return 0; 44 return 1; 45 } 46 47 bool check(int i,int j) 48 { 49 for (int k=1;k<=n;k++) 50 { 51 if (b[k].x>max(a[i].x,a[j].x)||b[k].x<min(a[i].x,a[j].x)) return 0; 52 if (b[k].y>max(a[i].y,a[j].y)||b[k].y<min(a[i].y,a[j].y)) return 0; 53 } 54 return 1; 55 } 56 57 58 int main() 59 { 60 //freopen("metal.in","r",stdin); 61 scanf("%d%d",&m,&n); 62 for (int i=1;i<=m;i++) scanf("%lf%lf%lf",&a[i].x,&a[i].y,&z); 63 for (int i=1;i<=n;i++) scanf("%lf%lf%lf",&b[i].x,&b[i].y,&z); 64 for (int i=1;i<=m;i++) 65 for (int j=1;j<=m;j++) 66 { 67 if (i==j) continue; 68 if (judge(i,j)) d[i][j]=f[i][j]=1; else d[i][j]=f[i][j]=inf; 69 } 70 for (int i=1;i<=m;i++) 71 if (single(i)) 72 { 73 printf("1\n"); 74 return 0; 75 } 76 for (int i=1;i<=m;i++) 77 for (int j=1;j<i;j++) 78 if (f[i][j]==1&&f[j][i]==1&&check(i,j)) 79 { 80 printf("2\n"); 81 return 0; 82 } 83 ans=inf; 84 for (int k=1;k<=m;k++) 85 { 86 for (int i=1;i<k;i++) 87 for (int j=1;j<i;j++) 88 ans=min(ans,f[i][j]+d[j][k]+d[k][i]); 89 for (int i=1;i<=m;i++) 90 for (int j=1;j<=m;j++) 91 f[i][j]=min(f[i][j],f[i][k]+f[k][j]); 92 } 93 if (ans==inf) ans=-1; 94 printf("%d\n",ans); 95 return 0; 96 }
AC without art, no better than WA !