1018 Public Bike Management (30 分)

问题描述:当某个站需要调整时,控制中心选择最近的路径到达该站,并调整路径上所有的站。注意:可以从路径上收集车。

解题思路:dijksta的应用。首先选择最短的路径,再判断所需携带的车辆。局部最优并不是全局最优。。。。。

所以dijkstra错误。应该用dfs。

dijkstra方法。25分

#include<iostream>
#include<vector>
using namespace std;
#define MAX 505
#define INF 0x0ffffff
int graph[MAX][MAX];
vector<int>C,path;
int Cmax,N,Sp;
void output(int v)
{
    if(v){
        output(path[v]);
        printf("->%d",v);
    }
}
void dijkstra()
{
    vector<bool>vis(N,0);
    vector<int>cost(N),sendbike(N,0),backbike(N,0);
    for(int i=1;i<N;++i){
        cost[i]=graph[0][i];//初始化
        if(cost[i]<INF){
            if(C[i]>Cmax)backbike[i]=C[i]-Cmax;
            else sendbike[i]=Cmax-C[i];
        }
    }
    for(int i=1;i<N;++i){
        int m=INF,v;
        for(int j=1;j<N;++j){//路径最小
            if(!vis[j]&&cost[j]<m)m=cost[i],v=i;
        }
        if(v==Sp){
            printf("%d 0",sendbike[v]);
            output(Sp);
            printf(" %d",backbike[v]);
            break;
        }
        vis[v]=1;
        for(int j=1;j<N;++j){//从v出发更新cost
            if(!vis[j]){
                int x=cost[v]+graph[v][j],b=0,s=0;
                if(C[j]>Cmax)b=C[j]-Cmax;
                else s=Cmax-C[j];
                int y=sendbike[v]+s-backbike[v];//v点之前带去的+j点带去的-v点需带回的。
                int z=backbike[v]-s+b;//v点带回的-j点带去的+j点带回的。
                if(y<0)y=0;//如果带去的为负,表示不需带
                if(z<0)z=0;//带回的为负,表示无需带回
                if(x<cost[j]){//路径更短
                    cost[j]=x;path[j]=v;
                    sendbike[j]=y;backbike[j]=z;
                }else if(x==cost[j]){//路径相等且可达
                    if(y<sendbike[j]||(y==sendbike[j]&&z<backbike[j])){
                        path[j]=v;
                        sendbike[j]=y;backbike[j]=z;
                    }
                }
            }
        }
    }

}
int main()
{
    freopen("test.txt","r",stdin);
    int M;
    scanf("%d%d%d%d",&Cmax,&N,&Sp,&M);
    ++N;Cmax/=2;
    C.resize(N);path.resize(N,0);
    for(int i=0;i<N;++i){
        for(int j=0;j<N;++j){
            graph[i][j]=INF;
        }
    }
    for(int i=1;i<N;++i)scanf("%d",&C[i]);
    while(M--){
        int c1,c2,t;
        scanf("%d%d%d",&c1,&c2,&t);
        graph[c1][c2]=graph[c2][c1]=t;
    }
    dijkstra();
    return 0;
}

AC代码:dfs

#include<iostream>
#include<vector>
using namespace std;
#define inf 999999
int cmax, n, sp, m, send,back;
#define MAX 505
int bike[MAX];
int route[MAX][MAX];
int visit[MAX];
int minsend = inf, minback = inf, mindis = inf;
vector<int> path, temppath;
void dfs(int v,int tempsend,int tempback,int tempdis)
{
	temppath.push_back(v);
	visit[v] = 1;
	if(v == sp){
		if(mindis > tempdis){
			minsend = tempsend; minback = tempback;
			mindis = tempdis; path = temppath;
		}else if(mindis == tempdis){
			if(minsend > tempsend){
				minsend = tempsend; minback = tempback;
				path = temppath;
			}else if(minsend == tempsend && minback > tempback){
				minback = tempback;
				path = temppath;
			}
		}
		return;
	}
	for(int i = 1; i <= n; i++)  //遍历相邻结点
	{
		if(visit[i] == 0&&route[v][i] != inf){
			int temp = bike[i] - cmax/2;
			int tempb = tempback, temps = tempsend;
			if(temp >= 0)
				tempb += temp;
			else{
				if(tempback + temp < 0){
					temps -= (tempback + temp);
					tempb = 0;
				}else{
					tempb += temp;
				}
			}
			dfs(i,temps,tempb,tempdis + route[v][i]);
			temppath.pop_back();   //倒退一个
			visit[i] = 0;          //又从temppath里最后一个点开始,查看可能路径
		}
	}
}
int main()
{
	//freopen("test.txt","r",stdin);
	scanf("%d %d %d %d",&cmax,&n,&sp,&m);
	fill(route[0],route[0] + 505 * 505, inf);
	for(int i = 0; i < n; i++)
		scanf("%d",&bike[i + 1]);
	for(int i = 0; i < m; i++){
		int ti, tj, v;
		scanf("%d %d %d",&ti,&tj,&v);
		route[ti][tj] = route[tj][ti] = v;
	}
	dfs(0,0,0,0);
	printf("%d ",minsend);
	for(int i = 0; i < path.size(); i++){
		if(i != 0)
			printf("->");
		printf("%d",path[i]);
	}
	printf(" %d",minback);
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值