小白月赛22 D : 收集纸片

D:收集纸片

考察点 : 全排列,对数据范围的估计程度
坑点  : 注意算最后回到初始的那步距离

析题得侃 :

一看题目最短路,诶呦,这不是最拿手的 BFS 走最短路吗?哈哈,定睛一看
这么多目的地,这还走个茄子,但是看看这道题的数据范围, 10,这不就完完
全全的可以暴力一发了,怎么暴力呢 ? 
我们并不知道那条线路会是最优的,所以我们可以用全排列列举出每一条线路,
然后最后取最小值即可。

Code :

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

#define INF 0x3f3f3f3f

#define x first
#define y second

using namespace std;

const int maxn = 25;

typedef pair<int,int>PII;

int T,n,res;
int start_x,start_y,end_x,end_y;

int a[maxn];

PII P[maxn];

int main(void) {
	int dist(int x,int y);
	void solve();
	scanf("%d",&T);
	while(T --) {
		scanf("%d%d",&end_x,&end_y);
		scanf("%d%d",&start_x,&start_y);
		scanf("%d",&n);
		for(int i = 1; i <= n; i ++) {
			scanf("%d%d",&P[i].x,&P[i].y);
		}
		P[n + 1].x = start_x,P[n + 1].y = start_y;
		res = INF;
		solve();
		printf("The shortest path has length %d
",res);
	}
	return 0;
}

int dist(int ax,int ay,int bx,int by) {
	return abs(ax - bx) + abs(ay - by);
}

void solve() {
        // 拿 a 数组的不同排列作为我们走的每条线路
	for(int i = 1; i <= n; i ++) {
		a[i] = i;
	}
	do {
		int ans = 0;
		for(int i = 1; i <= n; i ++) {
			if(P[a[i]].x > end_x || P[a[i]].y > end_y) continue;
			if(i == 1) ans += dist(start_x,start_y,P[a[i]].x,P[a[i]].y);
			else ans += dist(P[a[i]].x,P[a[i]].y,P[a[i - 1]].x,P[a[i - 1]].y); 
		}
                // 回到起点
		ans += dist(start_x,start_y,P[a[n]].x,P[a[n]].y);
		res = min(res,ans);

	} while(next_permutation(a + 1,a + 1 + n));
	return ;
}

后记:

一定要观察数据范围,根据数据范围采取对应的策略
原文地址:https://www.cnblogs.com/prjruckyone/p/12354295.html