TYVJ1061 Mobile Service - DP - 滚动数组
2018-03-28 21:28
295 查看
考虑花费和员工的位置,请求的位置都有关,可以设状态f(i,x,y,z)表示完成了前i个请求,三个员工现在位于x,y,z三处的最小花费,由i可以方便地推到i+1
(DP既可以由i-1推到i,也可以是i推到i+1,灵活应用才能写好方程)
状态转移方程是:
f(i+1,x,y,z)=min(f(i+1,qi+1,y,z),f(i,x,y,z)+c(x,qi+1))f(i+1,x,y,z)=min(f(i+1,qi+1,y,z),f(i,x,y,z)+c(x,qi+1))
f(i+1,x,y,z)=min(f(i+1,x,qi+1,z),f(i,x,y,z)+c(y,qi+1))f(i+1,x,y,z)=min(f(i+1,x,qi+1,z),f(i,x,y,z)+c(y,qi+1))
f(i+1,x,y,z)=min(f(i+1,x,y,qi+1),f(i,x,y,z)+c(z,qi+1))f(i+1,x,y,z)=min(f(i+1,x,y,qi+1),f(i,x,y,z)+c(z,qi+1))
复杂度太高了,不过卡的好的话可以有60分~
但是我们发现员工的位置是根据请求而改变的,所以当第i个请求完成后,一定有一个员工位于位置qiqi,并且是哪个员工位于qiqi对答案是没有影响的
所以我们可以降低一维数组
设f(i,x,y)f(i,x,y)表示完成了前i个请求后,有一个员工位于qiqi处,另外两个员工位于x,y处的最小花费
设q0q0为3,这样就可以从i=0推到i=n
注意一点,对于状态转移方程:f(i+1,x,qi)=min(f(i+1,x,qi),f(i,x,qi)+c(y,qi+1))f(i+1,x,qi)=min(f(i+1,x,qi),f(i,x,qi)+c(y,qi+1))
表示,y位置的员工前往了qi+1qi+1位置,并且x,qi不动,所以i+1处的状态依然是x,qi 而不是 x,qi+1qi+1
但是这样还!不!够!
我们发现内存仍然不够用,需要再优化一维
考虑到第i个阶段只和第i-1阶段有关,我们可以开
设k=0,由k^1来变换k
并且在这样滚动的时候需要想好k和k^1所代表的含义
我设k为下一个请求,k^1为已完成的最后一个请求,那么递推就是由k^1推到k的,并且最终答案也是
在取最终答案时不能把f[k]和f[k^1]比较
(DP既可以由i-1推到i,也可以是i推到i+1,灵活应用才能写好方程)
状态转移方程是:
f(i+1,x,y,z)=min(f(i+1,qi+1,y,z),f(i,x,y,z)+c(x,qi+1))f(i+1,x,y,z)=min(f(i+1,qi+1,y,z),f(i,x,y,z)+c(x,qi+1))
f(i+1,x,y,z)=min(f(i+1,x,qi+1,z),f(i,x,y,z)+c(y,qi+1))f(i+1,x,y,z)=min(f(i+1,x,qi+1,z),f(i,x,y,z)+c(y,qi+1))
f(i+1,x,y,z)=min(f(i+1,x,y,qi+1),f(i,x,y,z)+c(z,qi+1))f(i+1,x,y,z)=min(f(i+1,x,y,qi+1),f(i,x,y,z)+c(z,qi+1))
复杂度太高了,不过卡的好的话可以有60分~
但是我们发现员工的位置是根据请求而改变的,所以当第i个请求完成后,一定有一个员工位于位置qiqi,并且是哪个员工位于qiqi对答案是没有影响的
所以我们可以降低一维数组
设f(i,x,y)f(i,x,y)表示完成了前i个请求后,有一个员工位于qiqi处,另外两个员工位于x,y处的最小花费
设q0q0为3,这样就可以从i=0推到i=n
注意一点,对于状态转移方程:f(i+1,x,qi)=min(f(i+1,x,qi),f(i,x,qi)+c(y,qi+1))f(i+1,x,qi)=min(f(i+1,x,qi),f(i,x,qi)+c(y,qi+1))
表示,y位置的员工前往了qi+1qi+1位置,并且x,qi不动,所以i+1处的状态依然是x,qi 而不是 x,qi+1qi+1
但是这样还!不!够!
我们发现内存仍然不够用,需要再优化一维
考虑到第i个阶段只和第i-1阶段有关,我们可以开
f[2][201][201]
设k=0,由k^1来变换k
并且在这样滚动的时候需要想好k和k^1所代表的含义
我设k为下一个请求,k^1为已完成的最后一个请求,那么递推就是由k^1推到k的,并且最终答案也是
min(f[k][x][y])
在取最终答案时不能把f[k]和f[k^1]比较
#include <algorithm> #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 100000 + 10; int c[210][210],l,n,que[1010],qi=3,ans=0x3f3f3f3f + 200; int f[2][201][201]; int main() { scanf("%d %d", &l, &n); for(int i=1; i<=l; i++) for(int j=1; j<=l; j++) scanf("%d", &c[i][j]); for(int i=1; i<=n; i++) scanf("%d", que + i); memset(f,0x3f,sizeof(f)); f[0][1][2] = 0; int k = 0; for(int i=0; i<n; i++) { int x, y; k^=1; for(int j=1; j<=l; j++) for(int t=1; t<=l; t++) f[k][j][t] = 0x3f3f3f3f;//在统计时要对即将要更新的阶段重新赋最大值 for(int x=1; x<=l; x++) for(int y=1; y<=l; y++) { if(x==y || y==x) continue; f[k][x][y] = min(f[k][x][y],f[k^1][x][y] + c[qi][que[i+1]]); f[k][qi][y] = min(f[k][qi][y],f[k^1][x][y] + c[x][que[i+1]]); f[k][x][qi] = min(f[k][x][qi],f[k^1][x][y] + c[y][que[i+1]]); } qi = que[i+1]; } for(int x=1; x<=l; x++) for(int y=1; y<=l; y++) ans = min(ans, f[k][x][y]); printf("%d\n", ans); return 0; }
相关文章推荐
- [tyvj 1061] Mobile Service (线性dp 滚动数组)
- [TYVJ1061] Mobile Service|动态规划|滚动数组
- 【BZOJ1044】【tyvj3511】【codevs1870】木棍分割,二分答案+滚动数组+前缀和DP
- 从Tyvj1061 Mobile Service 看DP 来源与优化
- tyvj-1061 Mobile Service 基础dp
- tyvj P1519 博彩游戏(AC自动机+DP滚动数组)
- TYVJ 1061 Mobile Service(dp)
- Gym 100507G The Debut Album (滚动数组dp)
- Codeforces 570E,DP+滚动数组
- hdu 1024 Max Sum Plus Plus 一串数字中,m段连续数字最大和 滚动数组+dp
- poj 1036 Gangsters (DP:滚动数组)
- HDU ~ 1024 ~ Max Sum Plus Plus(DP+滚动数组)
- Happy Matt Friends HDU - 5119 (dp+滚动数组优化)
- UESTC - 594 我要长高(DP+滚动数组优化+单调队列优化)
- POJ 1159 DP+滚动数组
- POJ 1936 DP(公共序列+滚动数组)
- 2017 Hackatari Codeathon C. Arcade(DP)(滚动数组)
- Monkey and Banana(HDU 1069)解题报告(DP - 滚动数组)
- CF 590D Top Secret Task【dp递推+滚动数组】【好题】
- hdu 1024 Max Sum Plus Plus(滚动数组)(DP)