UVa #1336 Fixing the Great Wall (例题9-21)
2015-03-05 14:09
501 查看
这道题的动态规划部分还比较直观:
每次只有两个决策:向左走或者向右走。根据这个可以设计出状态:d(i,j,k)表示区间 [i,j] 已经被修复,目前处于最左端(k=0)或最右端(k=1)。
另外, c 值的总和是固定的,不论决策如何,最终都是一样的。因此不用加入状态转移。不过最后不要忘了加上它;
因此只用考虑 delta 就可以了。每次转移的代价就是区间 [i,j] 以外的所有结点的 delta 值乘以机器人移动所需时间。状态转移方程则是 d(i,j) = min( d(i-1, j)+cost1, d(i, j+1)+cost2)
但是有不少值得重视的细节:
1、dp数组不能每次全部置零,会TLE。解决办法是用一个vis数组标记
2、vis数组也不能每次置零,也会TLE。解决办法是用kase来充当标记
3、%.0f会自动四舍五入。需用floor截取整数部分
4、求一个连续区间的和(delta的和),自然应该用前缀和。
5、可以把起始位置当成一个待修复的结点,c和delta设为0。这样就不用在最后分类讨论了
6、对于一个结构体的数组,读取数据的时候直接用scanf("%d",&s[i].x),比读到一个临时变量然后调用构造函数好。
Run Time: 0.429s
每次只有两个决策:向左走或者向右走。根据这个可以设计出状态:d(i,j,k)表示区间 [i,j] 已经被修复,目前处于最左端(k=0)或最右端(k=1)。
另外, c 值的总和是固定的,不论决策如何,最终都是一样的。因此不用加入状态转移。不过最后不要忘了加上它;
因此只用考虑 delta 就可以了。每次转移的代价就是区间 [i,j] 以外的所有结点的 delta 值乘以机器人移动所需时间。状态转移方程则是 d(i,j) = min( d(i-1, j)+cost1, d(i, j+1)+cost2)
但是有不少值得重视的细节:
1、dp数组不能每次全部置零,会TLE。解决办法是用一个vis数组标记
2、vis数组也不能每次置零,也会TLE。解决办法是用kase来充当标记
3、%.0f会自动四舍五入。需用floor截取整数部分
4、求一个连续区间的和(delta的和),自然应该用前缀和。
5、可以把起始位置当成一个待修复的结点,c和delta设为0。这样就不用在最后分类讨论了
6、对于一个结构体的数组,读取数据的时候直接用scanf("%d",&s[i].x),比读到一个临时变量然后调用构造函数好。
Run Time: 0.429s
#define UVa "LT9-21.1336.cpp" //Fixing the Great Wall char fileIn[30] = UVa, fileOut[30] = UVa; #include<cstring> #include<cstdio> #include<algorithm> #include<vector> #include<cmath> using namespace std; struct Wall { int x; double c, d; bool operator < (const Wall& w2) const { return x < w2.x; } }; //Global Variables. Reset upon Each Case! const int maxn = 1000 + 10, LEFT = 0, RIGHT = 1; const double INF = 1e30; int n, v, sx; Wall walls[maxn]; double pref_d[maxn]; double sumc; double d[maxn][maxn][2]; int vis[maxn][maxn][2]; int kase = 0; ///// double cost(int l, int r, int s, int t) { double result = 0.0; double sumd = pref_d - (pref_d[r] - pref_d[l] + walls[l].d); int dist = abs(walls[s].x - walls[t].x); double tm = (double)dist / (double)v; result = sumd*tm; return result; } double dp(int l, int r, int k) { if(l == 0 && r == n) return 0; double& ans = d[l][r][k]; if(vis[l][r][k] == kase) return ans; vis[l][r][k] = kase; ans = INF; double s = (k==LEFT)?l:r; if(l > 0) //go left ans = min(ans, dp(l-1, r, LEFT) + cost(l, r, s, l-1)); if(r < n) //go right ans = min(ans, dp(l, r+1, RIGHT) + cost(l, r, s, r+1)); return ans; } int main() { memset(vis, 0, sizeof(vis)); while(scanf("%d%d%d", &n, &v, &sx) == 3 && n) { kase ++; walls[0].x = sx; walls[0].c = walls[0].d = 0; int sindex; sumc = 0; for(int i = 1; i < n+1; i ++) { scanf("%d%lf%lf", &walls[i].x, &walls[i].c, &walls[i].d); sumc += walls[i].c; } sort(walls, walls + n + 1); for(int i = 0; i < n+1; i ++) { if(walls[i].x == sx) sindex = i; pref_d[i] = walls[i].d; if(i) pref_d[i] += pref_d[i-1]; } printf("%.0f\n", floor(dp(sindex, sindex, LEFT)+(double)sumc)); } return 0; }
相关文章推荐
- Fixing the Great Wall UVA - 1336(区间dp+前缀和)
- Fixing the Great Wall UVA - 1336
- UVA 1336 Fixing the Great Wall(区间DP)
- uva 1336 - Fixing the Great Wall 修缮长城
- 100道动态规划——18 UVA 1336 Fixing the Great Wall 指标函数的分解,刷表法
- UVA 1336 Fixing the Great Wall - ACM/ICPC CERC 2004
- UVA-1336 Fixing the Great Wall(区间DP)
- UVa 1336 Fixing the Great Wall (区间DP)
- UVA - 1336 Fixing the Great Wall 记忆化搜索
- UVA 1336 Fixing the Great Wall——dp
- 【Uva 1336】Fixing the Great Wall
- Uva-1336-Fixing the Great Wall
- uva 1336 - Fixing the Great Wall
- UVA 1336 Fixing the Great Wall
- UVa1336 Fixing the Great Wall
- 【例题 6-21 UVA - 506】System Dependencies
- 【算法竞赛入门经典】6.5[图的概念和拓扑序] 例题6-21 UVa506
- 1336 - Fixing the Great Wall(DP)
- 例题10-21 多边形 UVa11971
- 紫书例题 10-21 UVa 11971 连续概率