您的位置:首页 > 其它

UVa 1632 Alibaba

2015-06-06 16:49 387 查看
Alibaba the famous character of our childhood stories would like to be immortal in order to keep bringing happiness to children. In order to rich this status he needs to prove that he is still able todo some unusual things. There are n treasures, (n<=10000) each in a different place located along a straight road. Each treasure has a time limit, after that it vanishes. Alibaba must take all the n treasures, and he must do it quickly. So he needs to figureout the order in which he should take the treasures before their deadlines starting from the most favorable position. Alibaba has the list of places and deadlines of the treasures. A place i is located at distance di from the leftmost end of theroad. The time it takes to take a treasure is instantaneous. Alibaba must find the smallest time by which he can take all the treasures.

Input 

The program input is from a text file. Each data set in the file stands for a particular set of treasures. For each set of treasures the input contains the number of treasures, and the list of pairsplace - deadline in increasing order of the locations. White spaces can occur freely between the numbers in the input. The input data are correct.

Output 

For each set of data the program prints the result to the standard output on a separate line. The solution is represented by the smallest time by which Alibaba can take all the treasures before theyvanish. If this is not possible then the output is "No solution".

Sample Input 

5
1 3
3 1
5 8
8 19
10 15

5
1 5
2 1
3 4
4 2
5 3

Sample Output 

11
No solution
#include <cstdio>#include <cstring>#include <utility>#include <algorithm>using namespace std;//long long inf = (1<<30);//long long inf = -1;int inf = (1<<30);// record[i][j][0]代表拿完第i,...,j的宝物,现在在第i点,所用最少时间// record[i][j][1]代表拿完第i,...,j的宝物,现在在第j点,所用最少时间//long long record[10010][10010][2];int record[10010][10010][2];// flag[i][j][k] == g_count 代表record[i][j][k]被计算过//int flag[10010][10010][2];int n;//pair<long,long> array[10010];pair<int,int> array[10010];/*int dist[10010];int time[10010];*/int g_count;int get_min(int begin, int end, int k);int main(){//	memset(flag, 0, sizeof(flag));//	g_count = 1;while(scanf("%d", &n) == 1){for(int i = 1; i <= n; i++){/*			long long x, y;scanf("%lld %lld", &x, &y);array[i] = pair<long long,long long>(x, y);*/int x, y;scanf("%d%d", &x, &y);array[i] = pair<int,int>(x, y);//			dist[i] = x;//			time[i] = y;record[i][i][0] = 0;record[i][i][1] = 0;}// 计算结果//		for(int k = 1; k <= n-1; k++)for(int i = n-1; i >= 1; i--){for(int j = i+1; j <= n; j++)//			for(int i = 1; i+k <= n; i++){//				int j = i+k;/*// 为0的情况,点在i.long long ans1 = -1;long long r1 = record[i+1][j][0];long long c1 = array[i+1].first - array[i].first;if(r1 != -1 && (r1+c1 <= array[i].second)){if(ans1 == -1)ans1 = r1+c1;elseans1 = min(ans1, r1+c1);}long long r2 = record[i+1][j][1];long long c2 = array[j].first - array[i].first;if(r2 != -1 && (r2+c2 <= array[i].second)){if(ans1 == -1)ans1 = r2+c2;elseans1 = min(ans1, r2+c2);}record[i][j][0] = ans1;// 为1的情况,点在jans1 = -1;r1 = record[i][j-1][0];c1 = array[j].first - array[i].first;if(r1 != -1 && (r1+c1 <= array[j].second)){if(ans1 == -1)ans1 = r1+c1;elseans1 = min(ans1, r1+c1);}r2 = record[i][j-1][1];c2 = array[j].first - array[j-1].first;if(r2 != -1 && (r2+c2 <= array[j].second)){if(ans1 == -1)ans1 = r2+c2;elseans1 = min(ans1, r2+c2);}record[i][j][1] = ans1;*/// 为0的情况,点在i.int ans1 = inf;int r1 = record[i+1][j][0];int c1 = array[i+1].first - array[i].first;if(r1 != inf && (r1+c1 < array[i].second)){ans1 = min(ans1, r1+c1);}int r2 = record[i+1][j][1];int c2 = array[j].first - array[i].first;if(r2 != inf && (r2+c2 < array[i].second)){ans1 = min(ans1, r2+c2);}record[i][j][0] = ans1;// 为1的情况,点在jans1 = inf;r1 = record[i][j-1][0];c1 = array[j].first - array[i].first;if(r1 != inf && (r1+c1 < array[j].second)){ans1 = min(ans1, r1+c1);}r2 = record[i][j-1][1];c2 = array[j].first - array[j-1].first;if(r2 != inf && (r2+c2 < array[j].second)){ans1 = min(ans1, r2+c2);}record[i][j][1] = ans1;}}//		int r = min(get_min(1, n, 0), get_min(1, n, 1));/*		long long r1 = record[1][0];long long r2 = record[1][1];if(r1 == -1 && r2 == -1)printf("No solution\n");else if(r1 == -1 && r2 != -1)printf("%lld\n", r2);else if(r1 != -1 && r2 == -1)printf("%lld\n", r1);elseprintf("%lld\n", min(r1,r2));*/int r = min(record[1][0], record[1][1]);if(r == inf)printf("No solution\n");elseprintf("%d\n", r);//		g_count++;}return 0;}/*// 计算结果// record[begin][end][0]代表拿完第begin,...,end的宝物,现在在第begin点,所用最少时间// record[begin][end][1]代表拿完第begin,...,end的宝物,现在在第end点,所用最少时间int get_min(int begin, int end, int k){if(flag[begin][end][k] == g_count)return record[begin][end][k];flag[begin][end][k] = g_count;if(begin == end){record[begin][end][k] = 0;return record[begin][end][k];}int ans = inf;if(k == 0){int r1 = get_min(begin+1, end, 0);int c1 = array[begin+1].first - array[begin].first;if(r1 != inf && r1+c1 <= array[begin].second)ans = min(ans, r1+c1);int r2 = get_min(begin+1, end, 1);int c2 = array[end].first - array[begin].first;if(r2 != inf && r2+c2 <= array[begin].second)ans = min(ans, r2+c2);record[begin][end][k] = ans;}else if(k == 1){int r1 = get_min(begin, end-1, 0);int c1 = array[end].first - array[begin].first;if(r1 != inf && r1+c1 <= array[end].second)ans = min(ans, r1+c1);int r2 = get_min(begin, end-1, 1);int c2 = array[end].first - array[end-1].first;if(r2 != inf && r2+c2 <= array[end].second)ans = min(ans, r2+c2);record[begin][end][k] = ans;}return record[begin][end][k];}*/
这道题和前面一道机器人修复长城类似,很容易可以想到状态d(i, j, k)表示取完第i,...,j个宝物,在i(k=0)或j(k=1)处,所花最少时间。
这题故意设置n为一万,一开始用记忆化搜索,TLE.
后来改成递推,AC.
感觉比较奇特的一点是,按照自己的方式递推(根据i和j之间的差值从1到n-1)
和汝佳书上方法(i从n-1到1,j从i+1到n), 时间花费多了一倍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: