http://acm.hdu.edu.cn/showproblem.php?pid=4362
(1)动态规划 d[i][j]=min(d[i-1][k] + |a[i-1][k].x - a[i][j].x| + a[i][j].p);
(2)去绝对值技巧:对上一层数轴上的 x 值排序,上面每个元素xL[j]=min(xL[j-1] , d[i-1][j]-a[i-1][j].x) ,xR[j]=min(xR[j+1] , d[i-1][j]+a[i-1][j].x) 。
(3)对于每个d[i][j] 只要通过a[i][j].x判断在上一层什么位置就行了,对于有序的序列查找位置。
动态规划+排序预处+二分
他人具体代码:
View Code
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> #define MAXM 55 #define MAXN 1010 using namespace std; struct point { int x,p; }a[MAXM][MAXN]; int d[MAXM][MAXN],m,n,xx; int xL[MAXN],xR[MAXN]; bool cmp(point A,point B) { if(A.x<B.x) return true; return false; } int find(int i,int key) { int L,R,M; L=0;R=n-1; while(L<=R) { M=(L+R)>>1; if(a[i][M].x<key) L=M+1; else if(a[i][M].x>key) R=M-1; else return M; } return L; } void work() { int i,j,k; sort(a[0],a[0]+n,cmp); for(i=0;i<n;i++) d[0][i]=abs(a[0][i].x-xx)+a[0][i].p; for(i=1;i<m;i++) { sort(a[i],a[i]+n,cmp); xL[0]=d[i-1][0]-a[i-1][0].x; for(j=1;j<n;j++) { xL[j]=min(d[i-1][j]-a[i-1][j].x,xL[j-1]); } xR[n-1]=d[i-1][n-1]+a[i-1][n-1].x; for(j=n-2;j>=0;j--) { xR[j]=min(d[i-1][j]+a[i-1][j].x,xR[j+1]); } for(j=0;j<n;j++) { k=find(i-1,a[i][j].x); if(k==n) d[i][j]=xL[n-1]+a[i][j].x+a[i][j].p; else if(k==0) d[i][j]=xR[0]-a[i][j].x+a[i][j].p; else { if(a[i-1][k].x==a[i][j].x) d[i][j]=min(xL[k]+a[i][j].x+a[i][j].p,xR[k]-a[i][j].x+a[i][j].p); else d[i][j]=min(xL[k-1]+a[i][j].x+a[i][j].p,xR[k]-a[i][j].x+a[i][j].p); } } } } int main() { int test,i,j; scanf("%d",&test); while(test--) { scanf("%d%d%d",&m,&n,&xx); for(i=0;i<m;i++) for(j=0;j<n;j++) scanf("%d",&a[i][j].x); for(i=0;i<m;i++) for(j=0;j<n;j++) scanf("%d",&a[i][j].p); work(); int ans=1000000000; for(i=0;i<n;i++) if(ans>d[m-1][i]) ans=d[m-1][i]; printf("%d\n",ans); } return 0; }