1072 部分正确

自己想到了是多源点求最短路径问题,用Dijkstra实现了1个多小时,还是2个4分case错误!

1: 初始化不应该用memeset设-1, 判断里面烦死了,图的算法还得练,不熟

2 :居然没有round函数,include <math.h>后还要加namespace! 

用ceil实现四舍五入到小数点后一位:

printf("%.1f", ceil(total*10/(float)n)/10);


#include <stdio.h>
#include <string.h>
#include <math.h>
#define MAX 999999
using namespace std;//不加namespace居然用不了math里的round, fuck!

int n, m, k, ds;

int map[1000+15][1000+15];
//int visit[1000+15][1000+15];

int dis[1000+15];

int visit[1000+15];//已访问

int itotalDis, iminDis, totalDis, minDis;

bool dijskra(int Gi){

	visit[Gi] = 1;//排除自己

	for(int i = 1; i <=n+m; i++){
			dis[i] = map[Gi][i];//map中-1表示没有路
	}
	
	

	for(int i = 1; i < n+m; i++){//做n+m - 1 次
		int curMin = MAX;
		
		int minPoint = -1;
		for(int j = 1; j <= n+m; j++){
			
			if(visit[j] == 0 && dis[j] != -1 && dis[j] < curMin){// 当前未访问的点中,找到路径最短的
				minPoint = j;
				curMin = dis[j];				
			}
		}

		if(curMin > ds){//找到从Gi 到当前点最短路径超过了Ds
			return false;
		}
		visit[minPoint] = 1;//加入已访问的集合

		//test
		//printf("visted %d\n", minPoint);
		
		if(minPoint <= n){//只记录到house 的距离,不记录到其他G的
			itotalDis += curMin;
			iminDis = iminDis > curMin ? curMin : iminDis;
		}

		for(int j = 1; j <= n+m; j++){
			if(map[j][minPoint] != -1 && (dis[j] == -1 || dis[j] > map[j][minPoint] + curMin)){// 更新所有点的最短路径
				dis[j] = map[j][minPoint] + curMin;
			}
		}

	}


	return true;


}

int main(){
	freopen("in.txt","r",stdin);

	scanf("%d%d%d%d",&n, &m, &k, &ds);

	memset(map, -1, sizeof(map));//-1表示没有路
	
	char p1[4], p2[4];
	int dist;
	int a, b;
	for(int i = 0; i < k; i++){
		
		scanf("%s%s %d",&p1, &p2, &dist);
		
		if(p1[0] == 'G'){//house is [1,N], then G1 is N+1,...,G10 is N+m
			a = m < 10 ? (p1[1]-'0') : 10;//m <= 10
			a += n;
		}else{
			a = p1[0]-'0';
		}
		
		if(p2[0] == 'G'){ 
			b = m < 10 ? (p2[1]-'0') : 10;
			b += n;
		}else{
			b = p2[0]-'0';
		}
		
		map[a][b] = dist;
		map[b][a] = dist;

		//test
		//printf("%d to %d = %d\n", a, b, dist);
	}



	totalDis = 0;
	minDis = -1;//要取最大的iminDis
	int Gres;
	bool isFound = false;

	for(int i = 1; i <= m; i++){//求从Gi出发,到各点的最短距离
		int Gi = n+i;
		itotalDis = 0;
		iminDis = MAX;

		memset(visit, 0, sizeof(visit));
		
		//test
		//printf("for Gi = %d\n", Gi);

		if (dijskra(Gi) ){

			//test
			//printf("itotalDis is %d\n",itotalDis);
			//printf("iminDis is %d\n", iminDis);

			if( (iminDis > minDis) || ( (iminDis == minDis) && (itotalDis < totalDis))){//取最大的minDis
				if(!isFound){
					isFound = true;
				}

				Gres = Gi;
				totalDis = itotalDis;
				minDis = iminDis;
			}
		} 

	}

	if(isFound){
		
		printf("G%d\n", Gres-n);
		printf("%.1f %.1f",(float)minDis, ( ceil( (float)totalDis*10/n) )/10);//四舍五入保留1位小数


		//test
		//printf("total is %d\n",totalDis);
		//printf("minDis is %d\n",minDis);
	}else{
		printf("No Solution");
	}
	

	return 0;
}


你可能感兴趣的:(1072 部分正确)