Description
Input
Output
Sample Input
2 2.5 4 ##### #S # # E# ##### 21 13 ############ #S## #E# # ## # # # # # # # # ### # # # # # # # # # # ## # # # ## # # # # ### # # # # ## # # # # # ## # # # # # ############
Sample Output
Case #1: 50.000% Case #2: 21.053%
题意:给一个迷宫,从S走到E,你可以将纵横(vertical)的路径拉伸(stretch),但是水平方向(horizontal)的路径长度保持为1个单位。 通过拉伸使S点到E点的最短距离为给定的L,求拉伸的比率(题目保证在0%~1000%之间)。
其实根据题目保证拉伸比率的范围就猜得到是二分。显然单调性是满足的,拉长距离后最短距离显然不会变短。然后通过最短路来判定,数据极其小,最短路用BFS就可以搞了,但是放在A*的作业里我还是用A*算了。。自己乱搞了了个估值函数:到终点的曼哈顿距离。。这个其实比实际值差很远,,但是满足小于等于实际值的基本特征,就能保证正确性,而且即使写丑了最坏比BFS多一个优先队列的log级别。
另外,读入数据不是很好搞。我赌他数据不会太坑。。也就是四周都有'#'号。。所以我先通过第一行的#个数判断M,每一行第一个字符#用cin,然后M-1个字符就用getchar了。。
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; #define DB double const DB EPS = 1e-4, INF = 1e5; int T, N, M; int xs, ys, xe, ye; DB L; char a[105][105]; const int d[4][2] = {{0,1},{0,-1},{1,0},{-1,0}}; struct ss { int x, y; DB pre, aft; ss () {} ss (int a,int b,DB c,DB d) {x=a; y=b; pre=c; aft=d;} //我一开始十分沙茶地写成了c=pre。。调了半小时才发现。。 bool operator < (const ss&a) const { return pre+aft > a.pre+a.aft; } }; #define Abs(a) ((a)>0?(a):-(a)) #define inmap(a,b) (a>0&&b>0&&a<=N&&b<=N) DB mht(int x, int y, DB rate) { //后半部分估值函数。曼哈顿距离 return rate/100.0*Abs(xe-x) + Abs(ye-y); } DB f[105][105]; //保存估值函数值 DB Astar(DB stre) { priority_queue<ss> Q; Q.push(ss(xs, ys, 0, mht(xs,ys,stre))); for (int i = 1; i<=N; ++i) for (int j = 1; j<=M; ++j) f[i][j] = INF; DB dis, g; ss t; int i, tx, ty; while (!Q.empty()) { t = Q.top(); Q.pop(); if (t.pre+t.aft > f[t.x][t.y]) continue; for (i = 0; i<4; ++i) { tx = t.x + d[i][0]; ty = t.y + d[i][1]; if (!inmap(tx,ty) || a[tx][ty]=='#') continue; if (i<2) dis = t.pre + 1; else dis = t.pre + stre / 100.0; if (tx == xe && ty == ye) return dis; g = mht(tx,ty,stre); if (dis+g < f[tx][ty]) { f[tx][ty] = dis+g; //dis是从起点到这里的距离,g是估计的到终点的距离下界。合成估值函数 Q.push(ss(tx, ty, dis, g)); } } } return -1; } DB work() { DB l = 0, r = 1000, mid = (l+r)/2.0, res; while (l+EPS < r) { res = Astar(mid); if (res > L) r = mid; else l = mid; mid = (l+r) / 2.0; } return mid; } int main() { int i, j; scanf("%d", &T); for (int ks = 1; ks<=T; ++ks) { scanf("%lf%d%s", &L, &N, a[1]+1); M = strlen(a[1]+1); for (i = 2; i<=N; ++i) { cin >> a[i][1]; for (j = 2; j<=M; ++j) a[i][j] = getchar(); for (j = 1; j<=M; ++j) { if (a[i][j] == 'S') xs = i, ys = j; if (a[i][j] == 'E') xe = i, ye = j; } } DB ans = work(); printf("Case #%d: %.3lf%%\n", ks, ans); } return 0; }