HDOJ4362-决策单调的DP

易得此题DP方程: dp[i][j]=min{dp[i-1][k]+abs(x[i-1][k]-x[i][j])}+cost[i][j]; //1<=i<=n,1<=j,k<=m;

当x[i-1][k]<=x[i][j]时,dp[i][j]=min{dp[i-1][k]-x[i-1[k]}+x[i][j]+cost[i][j]; (1)

当x[i-1][k]>x[i][j]时,dp[i][j]=min{dp[i-1][k]+x[i-1][k]}-x[i][j]+cost[i][j];  (2)

(1)和(2)式中的min{}部分均与j无关,单调性明显。

故可对点[i][j]按坐标排序,对于每层,从左往右(1),从右往左(2)两次,在坐标关系满足x[i-1][k]<=x[i][j](x[i-1][k]>x[i][j])中找到dp[i-1][k]-x[i-1][k](dp[i-1][k]+x[i-1][k])最小的点再做转移即可。

AC代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

const int NN=1010;
const int INF=0x3fffffff;

int dp[2][NN];
struct node{
    int x,w;
    bool operator <(const node a)const{
        return x<a.x;
    }
}a[NN][NN];

int main()
{
    int T,c,n,m,k,v,x0;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d%d",&n,&m,&x0);
        for (int i=1; i<=n; i++)
          for (int j=1; j<=m; j++) scanf("%d",&a[i][j].x);
        for (int i=1; i<=n; i++)
        {
            for (int j=1; j<=m; j++) scanf("%d",&a[i][j].w);
            sort(a[i]+1,a[i]+m+1);
            a[i][m+1].x=INF;
            a[i][0].x=-1;
        }

        //dp
        for (int j=1; j<=m; j++) dp[1][j]=abs(a[1][j].x-x0)+a[1][j].w;
        c=1;
        for (int i=2; i<=n; i++)
        {
            c=i%2;
            v=0; k=1;
            for (int j=1; j<=m; j++)
            {
                dp[c][j]=INF;
                while (a[i-1][k].x<=a[i][j].x)
                {
                    if (!v || dp[c^1][v]-a[i-1][v].x>dp[c^1][k]-a[i-1][k].x) v=k;
                    k++;
                }
                if (v)
                    dp[c][j]=min(dp[c][j],dp[c^1][v]-a[i-1][v].x+a[i][j].x+a[i][j].w);
            }
            v=0; k=m;
            for (int j=m; j; j--)
            {
                while (a[i-1][k].x>=a[i][j].x)
                {
                    if (!v || dp[c^1][v]+a[i-1][v].x>dp[c^1][k]+a[i-1][k].x) v=k;
                    k--;
                }
                if (v)
                    dp[c][j]=min(dp[c][j],dp[c^1][v]+a[i-1][v].x-a[i][j].x+a[i][j].w);
            }
        }

        int ans=INF;
        for (int j=1; j<=m; j++) ans=min(ans,dp[c][j]);
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(c,struct)