Ant Man CodeForces - 704B (图论,贪心)

大意: 给N个点,起点S终点T,每个点有X,A,B,C,D,根据I和J的X坐标可得I到J的距离计算公式

  • |xi - xj| + ci + bj seconds if j< i
  • |xi - xj| + di + aj seconds otherwise (j > i).

求从起点到终点,经过N个点恰好一次的最短路

 

这题好巧妙啊, 以前都没见过这种做法, 看题解说是要维护一条从S->T的链, 每次贪心往链里添点就行了, 显然这个贪心是与顺序无关的, 所以一定最优. 复杂度是$O(n^2)$的

#include <iostream>
#include <algorithm>
#include <cstdio>
#define REP(i,a,n) for(int i=a;i<=n;++i)
using namespace std;
typedef long long ll;

const int N = 1e3+10;
int n, s, t;
int x[N], a[N], b[N], c[N], d[N], nxt[N];
ll g[N][N];

int main() {
	scanf("%d%d%d", &n, &s, &t);
	REP(i,1,n) scanf("%d", x+i);
	REP(i,1,n) scanf("%d", a+i);
	REP(i,1,n) scanf("%d", b+i);
	REP(i,1,n) scanf("%d", c+i);
	REP(i,1,n) scanf("%d", d+i);
	REP(i,1,n) REP(j,1,n) if (i!=j) {
		if (j<i) g[i][j]=(ll)abs(x[i]-x[j])+c[i]+b[j];
		else g[i][j]=(ll)abs(x[i]-x[j])+d[i]+a[j];
	}
	ll ans = g[s][t];
	nxt[s] = t;
	REP(i,1,n) if (i!=s&&i!=t) {
		ll mi = 1e18;
		int pos;
		for (int j=s,k; j!=t; j=k) {
			k = nxt[j];
			ll d = g[j][i]+g[i][k]-g[j][k];
			if (mi>d) mi = d, pos = j;
		}
		ans += mi;
		nxt[i] = nxt[pos];
		nxt[pos] = i;
	}
	printf("%lld\n", ans);
}

猜你喜欢

转载自www.cnblogs.com/uid001/p/10421903.html
man