ACM Steps_Chapter Six_Section2

最短路

/*
思路:(Dijkstra 算法)
从单源点st开始,在外集合当中寻找离最短路集合最近的在外集合当中的点 i 。逐层往外延伸,
延伸的同时需要不断更新从st到外集合 j 点距离dis[j].
如果从最短集合里面经过 i 点再到 j 点的距离比原来的dis[j]还要近的话,那就更新dis[ j ]。
该算法的时间复杂度是(n^2),空间复杂度为(n^2)
*/
#include<iostream>
using namespace std;
#define MDIS    1000000
int dis[110],map[110][110],vis[110];//map[i][j]表示从i点到j点的距离。若两点间无通路,则距离为无穷大,vis[i]则表示i点是否已经在最短集合当中,dis[i]表示i 点到源点的最短距离

int main()
{
    int n,m,min,i,j,v,a,b,c;
    while(scanf("%d%d",&n,&m)!=EOF&&!(n==0&&m==0))
    {
                                                  for(i=1;i<=n;i++)
                                                          for(j=1;j<=n;j++) map[i][j]=MDIS;
    for(i=0;i!=m;i++)
    {
            scanf("%d%d%d",&a,&b,&c);
            map[a][b]=c;
            map[b][a]=c;
    }
    memset(vis,0,sizeof(vis));
    vis[1]=1;
    for(i=1;i<=n;i++)  dis[i]=map[1][i];
    for(i=1;i<n;i++)
    {
                     //cout<<"good"<<endl;
            min=MDIS;
            for(j=1;j<=n;j++)
            {
                              //cout<<"good"<<endl;
                    if(!vis[j]&&min>dis[j])//这里应该是j这个点没有放入最短集合当中 
                    {
                                           min=dis[j];
                                           v=j;
                    }
            }
            vis[v]=1;
            for(j=1;j<=n;j++)
            {
                             //cout<<"good"<<endl;
                    if(!vis[j]&&dis[v]+map[v][j]<dis[j]) dis[j]=dis[v]+map[v][j];
            }
    }
    printf("%d\n",dis[n]);
    }
    return 0;
}

Einbahnstrasse

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

const int N=110,INF=1000010;
int n,m,sz;
int g[N][N];
int q[1010];
map<string,int> mp;
void floyd()
{
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(g[i][j]>g[i][k]+g[k][j])
                    g[i][j]=g[i][k]+g[k][j];
}
int main()
{
    int C=0,c;
    while(scanf("%d%d%d",&n,&c,&m),n||m||c)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                g[i][j]=(i==j?0:INF);
        mp.clear(); sz=0;
        for(int i=0;i<=c;i++)
        {
            char u[15];
            scanf("%s",u);
            if(mp[u]==0) mp[u]=++sz;
            int t=mp[u];
            q[i]=t;
        }
        for(int i=0;i<m;i++)
        {
            char u[15],v[15],w[15];
            scanf("%s%s%s",u,w,v);
            if(mp[u]==0) mp[u]=++sz;
            if(mp[v]==0) mp[v]=++sz;
            int uu=mp[u], vv=mp[v], ww;
            sscanf(w+2,"%d",&ww);
            if(w[strlen(w)-1]=='>' && ww<g[uu][vv]) g[uu][vv]=ww;
            if(w[0]=='<' && ww<g[vv][uu]) g[vv][uu]=ww;
        }
        floyd();
        int ans=0;
        for(int i=1;i<=c;i++) ans+=g[1][q[i]]+g[q[i]][1];
        printf("%d. %d\n",++C,ans);
    }
    return 0;
}

Here We Go(relians) Again

#include"stdio.h"
#include"string.h"


struct A
{
	int total;
	int dis;
	int mem[6];
	int len[6];
}E[444];


int MIN(int a,int b)
{
	return a>b?b:a;
}


void SPFA(int s)
{
	int k,key;
	int hash[555];
	int i;
	int queue[888];


	queue[0]=s;
	key=1;
	k=0;
	memset(hash,0,sizeof(hash));
	hash[s]=1;
	while(k<key)
	{
		for(i=0;i<E[queue[k]].total;i++)
		{
			if(E[queue[k]].dis+E[queue[k]].len[i]<E[E[queue[k]].mem[i]].dis)
			{
				E[E[queue[k]].mem[i]].dis=E[queue[k]].dis+E[queue[k]].len[i];
				if(!hash[E[queue[k]].mem[i]])
				{
					hash[E[queue[k]].mem[i]]=1;
					queue[key++]=E[queue[k]].mem[i];
				}
			}
		}
		hash[queue[k++]]=0;
	}
}
int main()
{
	int n,m;
	int n_temp;
	int i,l;
	int limit;
	int temp;
	int t1,t2;
	char str[10];


	while(scanf("%d%d",&n,&m),n||m)
	{
		temp=(n+1)*(m+1);
		for(i=1;i<=temp;i++)	{E[i].total=0;E[i].dis=11111111;}


		n_temp=2*n+1;
		for(i=0;i<n_temp;i++)
		{
			if(i%2)	limit=m+1;
			else	limit=m;
			for(l=0;l<limit;l++)
			{
				scanf("%d%s",&temp,str);
				if(temp==0)	continue;
				temp=2520/temp;
				if(i%2==0)	{t1=(i/2)*(m+1)+l+1;t2=t1+1;}
				else		{t1=((i-1)/2)*(m+1)+l+1;t2=t1+m+1;}
				if(str[0]=='*')
				{
					E[t1].mem[E[t1].total]=t2;
					E[t1].len[E[t1].total++]=temp;
					E[t2].mem[E[t2].total]=t1;
					E[t2].len[E[t2].total++]=temp;
				}
				else if(str[0]=='v')
				{
					E[t1].mem[E[t1].total]=t2;
					E[t1].len[E[t1].total++]=temp;
				}
				else if(str[0]=='^')
				{
					E[t2].mem[E[t2].total]=t1;
					E[t2].len[E[t2].total++]=temp;
				}
				else if(str[0]=='>')
				{
					E[t1].mem[E[t1].total]=t2;
					E[t1].len[E[t1].total++]=temp;
				}
				else if(str[0]=='<')
				{
					E[t2].mem[E[t2].total]=t1;
					E[t2].len[E[t2].total++]=temp;
				}
			}
		}


		E[1].dis=0;
		SPFA(1);


		if(E[(n+1)*(m+1)].dis==11111111)	printf("Holiday\n");
		else								printf("%d blips\n",E[(n+1)*(m+1)].dis);
	}
	return 0;
}

Bus System

#include<stdio.h>
#include<math.h>
#define maxint 0x7f7f7f7f7f7f7f7fLL
_int64 map[102][102], dis[102][102], dist(_int64), l[5], c[5], x[102];
int n, m;
void init(), floyd();
int main()
{
    init();
    return 0;
}
void init()
{
    int cnum, i, j, k, a, b;
    scanf("%d", &cnum);
    for(k = 1; k <= cnum; ++k){
        printf("Case %d:\n", k);
        for(j = 1; j <= 4; ++j)
            scanf("%I64d", &l[j]);
        for(j = 1; j <= 4; ++j)
            scanf("%I64d", &c[j]);
        scanf("%d %d",&n, &m);
        for(j = 1; j <= n; ++j)
            scanf("%I64d", &x[j]);
        for(i = 1; i <= n; ++i)
            for(j = i + 1; j <= n; ++j)
                dis[i][j] = dis[j][i] = dist(x[i] - x[j]);
        floyd();
        for(j = 1; j <= m; ++j){
            scanf("%d %d",&a, &b);
            if(dis[a][b] != maxint)
                printf("The minimum cost between station %d and station %d is %I64d.\n",a, b, dis[a][b]);
            else
                printf("Station %d and station %d are not attainable.\n", a, b);
        }
    }
}
_int64 dist(_int64 t)
{
    if(t < 0) t = -t;
    if(t > 0 && t <=l[1])
        return c[1];
    if(t > l[1] && t <= l[2])
        return c[2];
    if(t > l[2] && t <= l[3])
        return c[3];
    if(t > l[3] && t <= l[4])
        return c[4];
    if(t > l[4]) 
        return maxint;
}
void floyd()
{
    int i, j, k;
    for(k = 1; k <= n; ++k)
        for(i = 1; i <= n; ++i)
            for(j = 1; j <= n; ++j)
                if(dis[i][k] != maxint && dis[k][j] != maxint && dis[i][j] > dis[i][k] + dis[k][j])
                    dis[i][j] = dis[i][k] + dis[k][j];
}

Transit search

#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include<queue>
using namespace std;
#define N 5050
#define NN 105
#define M 10001
#define inf 0x7fffffff
int place[8]={5120,2560,1280,640,320,160,80,40};
int fx,fy;
int ex,ey;
int m,n;

struct bus_stop{
	int x,y;
	char ch[30];
}B[N];
vector<bus_stop> bus_line[NN];

struct node{
	int next,v,w;
	node(){};
	node(int a,int b,int c){
		next=a;v=b;w=c;
	}
}E[M];
int head[NN],dis[NN],NE;
bool h[NN];
void init(){
	NE=0;
	memset(head,-1,sizeof(head));
}
void insert(int u,int v,int w){
	E[NE]=node(head[u],v,w);
	head[u]=NE++;
}
bool update(int u,int v,int w){
	if(dis[u]+w<dis[v]){
		dis[v]=dis[u]+w;
		return true;
	}
	return false;
}
void spfa(int beg,int end){
	queue<int> q;
	memset(h,0,sizeof(h));
	for(int i=0;i<=m+1;i++)
		dis[i]=inf;
	dis[beg]=0;
	q.push(beg);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		h[u]=0;
		for(int i=head[u];i!=-1;i=E[i].next){
			int v=E[i].v;
			if(update(u,v,E[i].w)&&!h[v]){
				h[v]=1;
				q.push(v);
			}
		}
	}
	if(dis[end]==inf){
		printf("take a taxi\n");
		return;
	}
	printf("%d\n",dis[end]);
}

int find(char *p){
	for(int i=0;i<n;i++)
		if(strcmp(p,B[i].ch)==0)
			return i;
}
bool find_bus(vector<bus_stop> p,vector<bus_stop> q){
	for(int i=0;i<p.size();i++)
		for(int j=0;j<q.size();j++)
			if(strcmp(p[i].ch,q[j].ch)==0)
				return true;
	return false;
}
void trans(char *p,int &x,int &y){
	x*=4;y*=4;
	for(int i=0;i<8;i++){
		if(p[i]=='1')
			y+=place[i];
		else if(p[i]=='2')
			x+=place[i];
		else if(p[i]=='3'){
			x+=place[i];
			y+=place[i];
		}
	}
}
double cal_dis(int fx,int fy,int ex,int ey){
	double temp1=(fx*1.0-ex*1.0)*(fx*1.0-ex*1.0);
	double temp2=(fy*1.0-ey*1.0)*(fy*1.0-ey*1.0);
	return sqrt(temp1+temp2);
}
int main(void){
	int t;
	scanf("%d",&t);
	while(t--){
		char s[10],e[10];
		scanf("%s%d%d",s,&fx,&fy);
		scanf("%s%d%d",e,&ex,&ey);
		trans(s,fx,fy);
		trans(e,ex,ey);
		scanf("%d",&n);
		for(int i=0;i<n;i++){
			scanf("%s",B[i].ch);
			scanf("%d%d",&B[i].x,&B[i].y);
		}
		scanf("%d",&m);
		for(int i=1;i<=m;i++){
			char ch[30];
			int k;
			scanf("%d",&k);
			bus_line[i].clear();
			while(k--){
				scanf("%s",ch);
				int id=find(ch);
				bus_line[i].push_back(B[id]);
			}
		}			
		if(cal_dis(fx,fy,ex,ey)<=2000.0){
			printf("walk there\n");
			continue;
		}
		int beg=0;
		int end=m+1;
		bool flag1,flag2;
		flag1=flag2=0;
		init();
		for(int i=1;i<=m;i++)
			for(int j=0;j<bus_line[i].size();j++){
				double k1=cal_dis(fx,fy,bus_line[i][j].x,bus_line[i][j].y);
				double k2=cal_dis(ex,ey,bus_line[i][j].x,bus_line[i][j].y);
				if(k1<=1000.0){
					flag1=true;
					insert(beg,i,1);
				}
				if(k2<=1000.0){
					flag2=true;
					insert(i,end,0);
				}
			}
		if(!flag1||!flag2){
			printf("take a taxi\n");
			continue;
		}
		for(int i=1;i<=m;i++)
			for(int j=i+1;j<=m;j++)
				if(find_bus(bus_line[i],bus_line[j])){
					insert(i,j,1);
					insert(j,i,1);
				}
		spfa(beg,end);
	}
}
				
				

find the safest road

/*
SPFA
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,st,ed,front,rear;
double mat[1005][1005],dis[1005];
int v[1005],q[1000001]; 
void spfa()
{
	int i,p;
	while(front<rear)
	{
		p=q[front++];
		v[p]=0;
		for(i=0;i<n;i++)
		{
			if(mat[p][i]==0||p==i)
			continue;
			if(dis[p]*mat[p][i]>dis[i])
			{
				dis[i]=dis[p]*mat[p][i];
				if(!v[i])
				{
					q[rear++]=i;
					v[i]=1;
				}
			}
		}
	}
}
int main()
{
	int i,j;
	while(scanf("%d",&n)!=EOF)
	{
		for(i=0;i<n;i++)
		for(j=0;j<n;j++)
		scanf("%lf",&mat[i][j]);
		scanf("%d",&m);
		while(m--)
		{
			scanf("%d%d",&st,&ed);
			memset(v,0,sizeof(v));
			memset(dis,0,sizeof(dis));
			v[st-1]=1;
			dis[st-1]=1;
			front=0;
			rear=1;
			q[front]=st-1;
			spfa();
			if(dis[ed-1]!=0)
			printf("%.3lf\n",dis[ed-1]);
			else
			printf("What a pity!\n");
		}
	}
	return 0;
}

How Many Paths Are There

 #include <cstdio>
 #include <cstring>
 using namespace std;
 
 const int N=60;
 int g[N][N],n,m;
 int dis[N][2],cnt[N][2];
 bool vis[N][2];
 void dijkstra(int p)
 {
     memset(vis,0,sizeof(vis));
     memset(cnt,0,sizeof(cnt));
     memset(dis,-1,sizeof(dis));
     dis[p][0]=0; cnt[p][0]=1;
     for(int k=0;k<2*n;k++)
     {
         int x,y,min=-1;
         for(int i=0;i<n;i++)
             if(!vis[i][0] && dis[i][0]!=-1 && (min==-1 || dis[i][0]<min))
                 min=dis[x=i][y=0];
             else if(!vis[i][1] && dis[i][1]!=-1 && (min==-1 || dis[i][1]<min))
                 min=dis[x=i][y=1];
         if(min==-1) break;
         vis[x][y]=true;
         for(int v=0;v<n;v++) if(g[x][v]!=-1)
         {
             int tdis=min+g[x][v];
             if(dis[v][0]==-1 || tdis<dis[v][0])
             {
                 dis[v][1]=dis[v][0];
                 cnt[v][1]=cnt[v][0];
                 dis[v][0]=tdis;
                 cnt[v][0]=cnt[x][y];
             }
             else if(tdis==dis[v][0]) cnt[v][0]+=cnt[x][y];
             else if(dis[v][1]==-1 || tdis<dis[v][1])
             {
                 dis[v][1]=tdis;
                 cnt[v][1]=cnt[x][y];
             }
             else if(tdis==dis[v][1]) cnt[v][1]+=cnt[x][y];
         }
     }
 }
 int main()
 {
     int s,e;
     while(~scanf("%d%d%d%d",&n,&m,&s,&e))
     {
         memset(g,-1,sizeof(g));
         for(int i=0;i<m;i++)
         {
             int u,v,w;
             scanf("%d%d%d",&u,&v,&w);
             if(g[u][v]==-1 || w<g[u][v]) g[u][v]=w;
         }
         dijkstra(s);
         printf("%d %d\n",dis[e][1],cnt[e][1]);
     }
 }

In Action

/*
题意:有n个基地,分别标号1..n,每个地点都有一定的能量,选择一些基地使得能量和大于总和的一半,当然这些选择的点是与0连通的。起点在编号为0的基地。
分析:第一步:求起点为0,到其他点的最短路,
        第二步:01背包,cost[i] 为起点到 i 的最短路,weight[i] 为 i 的能量。
        */
 #include<iostream>
 #include<cstring>
 #include<cstdio>
 #define MAXN 101
 #define MAXV 10001
 #define INF 0x3fffffff
 
 using namespace std;
 
 int dis[MAXN][MAXN],d[MAXV],cost[MAXN],weight[MAXN];
 
 void floyd(int n)
 {
     int i,j,k;
     for(k=0;k<=n;k++)
         for(i=0;i<=n;i++)
             for(j=0;j<=n;j++)
                 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
 }
 
 void ZeroOnePack(int n,int v)
 {
     int i,j;
     memset(d,0,sizeof(d));
     for(i=1;i<=n;i++)
         for(j=v;j>=cost[i];j--)
             d[j]=max(d[j],d[j-cost[i]]+weight[i]);
 }
 
 int main()
 {
 #ifndef ONLINE_JUDGE
     freopen("in.txt","r",stdin);
 #endif
     int test,n,m,x,y,z,i;
     scanf("%d",&test);
     while(test--)
     {
         scanf("%d%d",&n,&m);
         for(x=0;x<=n;x++)
             for(y=0;y<=n;y++)
                 dis[x][y]=dis[y][x]=(x==y?0:INF);
         for(i=0;i<m;i++)
         {
             scanf("%d %d %d",&x,&y,&z);
             if(dis[x][y]>z)
                 dis[x][y]=dis[y][x]=z;
         }
         int sump=0;
         for(i=1;i<=n;i++)
         {
             scanf("%d",&weight[i]);
             sump+=weight[i];
         }
         sump=(sump>>1)+1;
         floyd(n);
         bool flag=false;
         int sumv=0;
         for(i=1;i<=n;i++)
         {
             cost[i]=dis[0][i];
             if(cost[i]!=INF) sumv+=cost[i];
         }
         ZeroOnePack(n,sumv);
         flag=false;
         for(i=1;i<=sumv;i++)
         {
             if(d[i]>=sump)
             {
                 printf("%d\n",i);
                 flag=true;
                 break;
             }
         }
         if(!flag) printf("impossible\n");
     }
     return 0;
 }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值