训练总结 8.7

来源:互联网 发布:mysql数据库管理 编辑:程序博客网 时间:2024/05/29 11:15

  今天做的题都是图论的题,两道floyd算法题,两道prim算法题,还有一道Dijkstra算法题。思路和写法都是相似的,题也比较简单。

  1、Frogger

  prim算法求最小生成树,找最小生成树的最大权值。

  2、Stockbroker  Grapevine

  floyd算法,该题中图不一定是连通的。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;

#define q 0xfffffff

int n,m,sum,s,p;
int mp[101][101];

int main()
{
    while(scanf("%d",&n)&&n)
    {
        //memset(mp,q,sizeof(mp));//不能用memset函数赋极大值
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                mp[i][j]=q;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&m);
            for(int j=1;j<=m;j++)
            {
                int x1,y1;
                cin>>x1>>y1;
                mp[i][x1]=y1;
            }
        }
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    if(i!=k&&i!=j&&k!=j&&mp[k][j]<q&&mp[i][k]<q)
                        mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
                }
            }
        }
        sum=q;
        for(int i=1;i<=n;i++)
        {
            s=0;
            for(int j=1;j<=n;j++)
            {
                if(i==j)continue;
                s=max(s,mp[i][j]);
            }//同一起点值最大的为信息传播给所有人的时间
            if(sum>s)
            {
                sum=s;
                p=i;
            }
        }
        if(sum==q)
            printf("disjoint\n");
        else
            printf("%d %d\n",p,sum);
    }
    return 0;
}

 

 

3、昂贵的聘礼

这道题比较麻烦,在初始化的时候,将已知条件转化为符合图论算法的条件。

 

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;

int m,n;
int p[101],l[101],x[101];
int t,v;
bool vis[101];
int money[101][101];//用j商品再加上金币money[i][j]即可换购i商品
int dis[101];
bool change[101];

int dijkstra()
{
    memset(vis,0,sizeof(vis));
    //memset(dis,0xfffffff,sizeof(dis));
    for(int i=1;i<=n;i++)
        dis[i]=0xfffffff;
    dis[1]=0;
    for(int i=1;i<=n;i++)
    {
        int pos=-1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&change[j]&&(pos==-1||dis[j]<dis[pos]))
                pos=j;
        }
        vis[pos]=true;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&change[j]&&dis[j]>dis[pos]+money[pos][j])
                dis[j]=dis[pos]+money[pos][j];
        }
    }
    int mmin=0xfffffff;
    for(int i=1;i<=n;i++)
    {
        dis[i]+=p[i];
        mmin=min(mmin,dis[i]);
    }
    return mmin;
}
/*int dijkstra()
{
 memset(vis,false,sizeof vis);
 for(int i=1;i<=n;i++)
  dis[i]=0xfffffff;
 dis[1]=0;
 for(int i=1;i<=n;i++)
 {
  int pos=-1;
  for(int j=1;j<=n;j++)
  {
   if(!vis[j]&&change[j]&&(pos==-1||dis[j]<dis[pos]))
    pos=j;
  }
  vis[pos]=true;
  for(int j=1;j<=n;j++)
  {
   if(!vis[j]&&change[j]&&dis[j]>dis[pos]+money[pos][j])
   {
    dis[j]=dis[pos]+money[pos][j];
   }
  }
 }
 int mine=0xfffffff;
 for(int i=1;i<=n;i++)//dis[i]存的是从第1号商品到第i-1号商品的所有优惠价格  这时还应该加上第i件商品的原价 因为他是第一件不能优惠
 {
  dis[i]+=p[i];
  mine=min(mine,dis[i]);
 }
 return mine;
}*/

int main()
{
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    money[i][j]=0;
                else
                    money[i][j]=0xfffffff;
            }
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&p[i],&l[i],&x[i]);
            while(x[i]--)
            {
                scanf("%d%d",&t,&v);
                money[i][t]=min(money[i][t],v);
            }
        }
        int Min=0xfffffff;
        for(int i=0;i<=m;i++)
        {
            memset(change,0,sizeof(change));
            for(int j=1;j<=n;j++)
            {
                if(l[j]>=l[1]-m+i&&l[j]<=l[1]+i)
                    change[j]=true;
            }
            Min=min(Min,dijkstra());
        }
        printf("%d\n",Min);
    }
    return 0;
}

 

4、Truck  History

很简单的prim算法

 

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
using namespace std;

int n,k;
char ch[2001][11];
int mp[2001][2001];
bool vis[2001];
int dis[2001];

int prim()
{
    /*int sum=0;
    int next,Min;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
        dis[i]=mp[1][i];
    vis[1]=1;
    for(int i=2;i<=n;i++)
    {
        Min=0xfffffff;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&Min>dis[j])
            {
                Min=dis[j];
                next=j;
            }
        }
        sum+=Min;
        vis[next]=1;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&dis[j]>mp[next][j])
                dis[j]=mp[next][j];
        }
    }
    return sum;*/

    int ans=0;
    for(int i=0;i<=n;i++)
        dis[i]=0xfffffff;//一开始没有给dis[0]赋值,找了好长时间的错
    memset(vis,0,sizeof(vis));
    dis[1]=0;
    while(1)
    {
        //cout<<ans<<endl;
        k=0;
        for(int j=1;j<=n;j++)
            if(!vis[j]&&dis[j]<dis[k])
                k=j;
        if(!k)break;
        vis[k]=1;
        ans+=dis[k];
        for(int j=1;j<=n;j++)
        {
            if(dis[j]>mp[k][j])
                dis[j]=mp[k][j];
        }
    }
    return ans;
    /*int t,pos;
    double Min,Max=0;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
        low[i]=mp[1][i];
    vis[1]=1;
    pos=1;
    t=0;
    for(int i=1;i<n;i++)
    {
        Min=0xfffffff;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&low[j]<Min)
            {
                Min=low[j];
                pos=j;
            }
        }
        if(Min>Max)
            Max=Min;
        if(pos==2)
            return Max;
        vis[pos]=1;
        for(int j=1;j<=n;j++)
            if(!vis[j]&&low[j]>mp[pos][j])
                low[j]=mp[pos][j];
    }*/
}

int main()
{
    while(scanf("%d",&n)&&n)
    {
        //memset(mp,0,sizeof(mp));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                if(i==j)mp[i][j]=0;
                else
                    mp[i][j]=0xfffffff;
            }
        for(int i=1;i<=n;i++)
        {
            scanf("%s",ch[i]);
        }
        for(int i=1;i<n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                int s=0;
                for(int k=0;k<7;k++)
                    if(ch[i][k]!=ch[j][k])
                        s++;
                mp[j][i]=mp[i][j]=s;
            }
        }
        prim();
        printf("The highest possible quality is 1/%d.\n",prim());
    }
    return 0;
}

 

5、Arbitrage

不同货币之间的转化,问是否存在路径使钱增加。floyd算法的变型,化加为乘,求最大值。 

#include<iostream>
#include<algorithm>
#include<map>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;

int n,m;
double mp[31][31];
map<string,int>ma;

int main()
{
    int cas=1;
    while(scanf("%d",&n)!=EOF&&n)
    {
        for(int i=1;i<=n;i++)
        {
            string s;
            cin>>s;
            ma[s]=i;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    mp[i][j]=1.0;
                else
                    mp[i][j]=0;
            }
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            char a[101],b[101];
            double c;
            scanf("%s%lf%s",a,&c,b);
            mp[ma[a]][ma[b]]=c;
        }
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    mp[i][j]=max(mp[i][j],mp[i][k]*mp[k][j]);
                }
            }
        }
        bool falg=false;
        for(int i=1;i<=n;i++)
        {
            if(mp[i][i]>1.0)
            {
                falg=true;
                break;
            }
        }
        if(falg)
            printf("Case %d: Yes\n",cas);
        else
            printf("Case %d: No\n",cas);
        cas++;
    }
    return 0;
}

 

原创粉丝点击