[HAOI2005] 希望小学

来源:互联网 发布:如何建立家庭网络共享 编辑:程序博客网 时间:2024/04/30 02:00

 [HAOI2005] 希望小学

★   输入文件:hopeschool.in   输出文件:hopeschool.out   简单对比
时间限制:1 s   内存限制:128 MB

【问题描述】

地处偏僻山区的X乡有N个自然村,目前还没有一所小学,孩子们要么不上学,要么需要翻过一座大山到别处上学。如今好啦,有一位热心人士准备捐款在某个自然村建立一所希望小学。
通过调查发现,X乡各个村庄之间的道路较为复杂,有平路、上坡和下坡。考虑到每个村孩子们的人数不同,走上坡、下坡和平路的速度也不同,?男孩和女孩走路速度也不同,请你为X乡选择一个最合适建立希望小学的村庄,使得所有的孩子花在路上的总时间最少。

【输入文件】

hopeschool.in

第1行: N B1 B2 B3 G1 G2 G3 (村庄数、男孩分别走平路、上坡、下坡每千米花费的时间以及女孩分别走平路、上坡、下坡每千米花费的时间)
第2行: Xl X2……Xn (Xi表示第i个村要上学的男孩人数)
第3行: Y1 Y2……Yn (Yi表示第i个村要上学的女孩人数)
第4行: K (道路数)
第5—K+4行: Ai Bi Si1 Si2 Si3 (村庄Ai到村庄Bi,平路Sil千米,上坡Si2千米,下坡Si3千米,i=1,2,…,K)

【输出文件】

hopeschool.out

T(将要建立希望小学村庄的编号)

【约束条件】

(1) N<=30, Xi<=20, Yi<=20
(2) K<=100, 每条路的长度<=30千米
(3) B1,B2,B3,G1,G2,G3为整数,都小于10个单位时间/每千米
(4) 每条道路只给出一组数据。例如:5 8 7 10 3表示从村庄5往村庄8走,平路
有7千米,上坡10千米。 下坡3千米;当然也表示从村庄8往村庄5走,平路有7千米,
上坡3千米。下坡10千米。

【输入输出样例】

hopeschool.in

2 2 2 1 2 3 2 
10 12 
5 4 

1 2 10 2 1

hopeschool.out

2

错误代码:

/**这是一道图论中,应用Floyd算法的一道简单题。总结下面这段代码错误之处:   goto->Label1   根据题目的要求,在这里男女并不是分开走的,就是说,男生女生都走一条路,并不是男生走属于自己的那条最短路,女生走属于自己的那条最短路。   goto->Label2   (这个错误,感觉自己脑子短路了....)   从A到B的上坡,在B到A的路上就变成下坡了,同样的,从A到B的下坡也是会变成上坡。我的错误就在于没有上坡变下坡,下坡变上坡,结果算时间时出现了错误。**/#include <iostream>#include <cstdio>#include <cmath>#include <cstring>using namespace std;int N,B1,B2,B3,G1,G2,G3;int K;int boy[33]= {0},girl[33]= {0};//Label1int mboy[33][33]= {0},mgirl[33][33]= {0};int ans;void read(){    int i;    cin>>N>>B1>>B2>>B3>>G1>>G2>>G3;    for(i=1; i<=N; i++)        scanf("%d",&boy[i]);        for(i=1; i<=N; i++)        scanf("%d",&girl[i]);    cin>>K;    memset(mboy,2,sizeof(mboy));    memset(mgirl,2,sizeof(mgirl));    for(i=1; i<=N; i++)    {        mboy[i][i]=0;        mgirl[i][i]=0;    }    for(i=1; i<=K; i++)    {        int j,k,l1,l2,l3;        scanf("%d%d%d%d%d",&j,&k,&l1,&l2,&l3);        mboy[j][k]=l1*B1+l2*B2+l3*B3;        mboy[k][j]=mboy[j][k];//Label2        mgirl[j][k]=l1*G1+l2*G2+l3*G3;        mgirl[k][j]=mgirl[j][k];    }}int min(int a,int b){    return a<b?a:b;}void Floyd(int a[33][33],int n){    int i,j,k;    for(i=1; i<=n; i++)        for(j=1; j<=n; j++)            for(k=1; k<=n; k++)            {                if(j==k)                    continue;                a[j][k]=min(a[j][k],a[j][i]+a[i][k]);            }}void deal(){    int i,j,Min=1000000;    Floyd(mboy,N);    Floyd(mgirl,N);    for(i=1;i<=N;i++)    {        int sum=0;        for(j=1;j<=N;j++)        {//label1            sum+=mboy[i][j]*boy[j]+mgirl[i][j]*girl[j];        }        if(sum<Min)        {            Min=sum;            ans=i;        }        cout<<sum<<"::"<<Min<<endl;    }}void print(){    cout<<ans<<endl;}int main(){    freopen("hopeschool.in","r",stdin);    freopen("hopeschool.out","w",stdout);    read();    deal();    print();    return 0;}/****8 2 3 1 3 4 210 10 10 10 10 10 10 102 2 2 2 2 2 2 2111 2 4 2 22 3 5 1 33 4 6 0 04 5 3 5 25 6 9 0 16 7 8 2 07 1 5 2 21 8 0 5 07 8 0 5 03 8 2 5 04 8 0 6 04**/

正确代码:

/**正解:     其实就是把每条边算出来,再构图,然后用Floyd算法算出最短路,     求其他点到某一点的最短路之和,谁的和最小,就把村庄建在哪。**/#include <iostream>#include <cstdio>#include <cmath>#include <cstring>using namespace std;int N,B1,B2,B3,G1,G2,G3;int K;int boy[33]= {0},girl[33]= {0};int Map[33][33]= {0};int ans;void read(){    int i;    cin>>N>>B1>>B2>>B3>>G1>>G2>>G3;    for(i=1; i<=N; i++)        scanf("%d",&boy[i]);    for(i=1; i<=N; i++)        scanf("%d",&girl[i]);    cin>>K;    memset(Map,1,sizeof(Map));    for(i=1; i<=N; i++)        Map[i][i]=0;    for(i=1; i<=K; i++)    {        int j,k,l1,l2,l3;        scanf("%d%d%d%d%d",&j,&k,&l1,&l2,&l3);        Map[j][k]=boy[j]*(l1*B1+l2*B2+l3*B3)+girl[j]*(l1*G1+l2*G2+l3*G3);        Map[k][j]=boy[k]*(l1*B1+l2*B3+l3*B2)+girl[k]*(l1*G1+l2*G3+l3*G2);    }}int min(int a,int b){    return a<b?a:b;}void Floyd(int a[33][33],int n){    int i,j,k;    for(i=1; i<=n; i++)        for(j=1; j<=n; j++)            for(k=1; k<=n; k++)            {                if(j==k)                    continue;                a[j][k]=min(a[j][k],a[j][i]+a[i][k]);            }}void deal(){    int i,j,Min=1000000;    Floyd(Map,N);    for(i=1; i<=N; i++)    {        int sum=0;        for(j=1; j<=N; j++)            sum+=Map[j][i];        if(sum<Min)        {            Min=sum;            ans=i;        }        //cout<<sum<<"::"<<Min<<endl;    }}void print(){    cout<<ans<<endl;}int main(){    freopen("hopeschool.in","r",stdin);    freopen("hopeschool.out","w",stdout);    read();    deal();    print();    return 0;}



原创粉丝点击