1027: [JSOI2007]合金

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1027

显然对于每种金属,我们只用存任意两个量,因为第三个可以用1减去存下来的两个得到。
把这些二元组作为坐标映射到坐标系上。如果有解,则所有需要的材料必在原材料所组成的一个凸包中。
对于任意两个原材料,若所有需要的材料都在连边同一侧或边上,则将两点间连一条长度为1的边,这样问题就转化为最小环,用floyd求即可。
#include <iostream>
#include 
<cstring>
#include 
<cstdlib>
#include 
<cstdio>
#include 
<cmath>
#include 
<ctime>
using namespace std;
const int MaxN=501;
const int oo=100000001;
const double e=1e-10;

struct point
{
    
double x,y;
}
;

point 
operator -(point a,point b)
{
    point c;
    c.x
=a.x-b.x;
    c.y
=a.y-b.y;
    
return c;
}


bool operator ==(point a,point b)
{
    
return a.x==b.x && a.y==b.y;
}


int n,m;
point a[MaxN],b[MaxN];
int c[MaxN][MaxN],d[MaxN][MaxN];

double det(point a,point b)
{
    
return (a.x*b.y-a.y*b.x);
}


int pd(point a,point b,point c)
{
    
double k=det(b-a,c-a);
    
if (k>=-&& k<=e) return 0;
    
if (k>0return 1;
    
if (k<0return -1;
}


void init()
{
    cin
>>n>>m;
    
for (int i=0;i<n;i++)
    
{
        
double z;
        cin
>>a[i].x>>a[i].y>>z;
    }

    
for (int i=0;i<m;i++)
    
{
        
double z;
        cin
>>b[i].x>>b[i].y>>z;
    }

}


int treat()
{
    
for (int i=0;i<n;i++)
    
{
        
bool f=1;
        
for (int j=0;j<m;j++)
        
{
            
if (a[i].x*b[j].y!=a[i].y*b[j].x || a[i].y*(1-b[j].x-b[j].y)!=(1-a[i].x-a[i].y)*b[j].y || a[i].x*(1-b[j].x-b[j].y)!=(1-a[i].x-a[i].y)*b[j].x)
            
{
                f
=0;
                
break;
            }

        }

        
if (f==1)
        
{
            
return 1;
        }

    }

    
for (int i=0;i<n;i++)
    
{
        
for (int j=0;j<n;j++)
        
{
            
if (i==j)
            
{
                
continue;
            }

            
if (a[i]==a[j])
            
{
                c[i][j]
=oo;
                
continue;
            }

            
bool f=1;
            
int k;
            
for (k=0;pd(a[i],a[j],b[k])==0 && k<&& b[k].x<=max(a[i].x,a[j].x) && b[k].x>=min(a[i].x,a[j].x);k++);
            
if (k==m)
            
{
                
return 2;
            }

            
for (int k=0;k<m;k++)
            
{
                
if (pd(a[i],a[j],b[k])<0)
                
{
                    f
=0;
                    
break;
                }

            }

            
if (f==1)
            
{
                c[i][j]
=1;
            }

            
else
            
{
                c[i][j]
=oo;
            }

        }

    }

    
return 0;
}


int floyd()
{
    
int ans=oo;
    memcpy(d,c,
sizeof(d));
    
for (int k=0;k<n;k++)
    
{
        
for (int i=0;i<n;i++)
        
if (i!=k)
            
for (int j=0;j<n;j++)
            
{
                
if (j!=&& j!=i)
                ans
=min(ans,d[i][j]+c[k][i]+c[j][k]);
            }

        
for (int i=0;i<n;i++)
            
for (int j=0;j<n;j++)
            
{
                d[i][j]
=min(d[i][j],d[i][k]+d[k][j]);
            }

    }

    
return ans;
}


int main()
{
    init();
    
int f=treat();
    
if (f!=0)
    
{
        cout
<<f<<endl;
    }

    
else
    
{
        
int ans=floyd();
        
if (ans==oo)
        
{
            cout
<<-1<<endl;
        }

        
else
        
{
            cout
<<ans<<endl;
        }

    }

    
return 0;
}


posted on 2013-02-13 21:35 Kiro 阅读(260) 评论(0)  编辑 收藏 引用 所属分类: 衡八oj