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 to do 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 figure out 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 the road. 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 pairs place - 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 they vanish. 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; else ans1 = 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; else ans1 = min(ans1, r2+c2); } record[i][j][0] = ans1; // 为1的情况,点在j ans1 = -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; else ans1 = 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; else ans1 = 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的情况,点在j ans1 = 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][n][0]; long long r2 = record[1][n][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); else printf("%lld\n", min(r1,r2)); */ int r = min(record[1][n][0], record[1][n][1]); if(r == inf) printf("No solution\n"); else printf("%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), 时间花费多了一倍。
本文介绍了一个关于阿里巴巴角色寻找宝藏的算法问题。该问题要求计算阿里巴巴如何在最短时间内收集所有带有时间限制的宝藏。文章提供了详细的算法实现过程,并讨论了递推方法的应用。
693

被折叠的 条评论
为什么被折叠?



