HDU-4363-Dragon Ball

这个题其实就是个DP,只不过需要优化一下,用到类似单调队列~

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf=1<<29;
const int maxn=1100;
const int maxm=60;
int n,m;
int x,dp[maxm][maxn];
struct Node
{
    int sa;
    int sb;
    bool operator < (const Node &a)const{
        return sa<a.sa;
    }
}a[maxm][maxn];
void Init()
{
    for(int i=0;i<=m;i++)
        for(int j=0;j<=n;j++)
            dp[i][j]=inf;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&m,&n,&x);
        Init();
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&a[i][j].sa);
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&a[i][j].sb);
        for(int i=0;i<m;i++)
            sort(a[i],a[i]+n);
        for(int i=0;i<n;i++)
            dp[0][i]=abs(a[0][i].sa-x)+a[0][i].sb;
        for(int i=1;i<m;i++)
        {
            int index=0;
            int mini=inf;
            for(int j=0;j<n;j++)
            {
                while(index<n&&a[i-1][index].sa<=a[i][j].sa)
                {
                    mini=min(mini,dp[i-1][index]-a[i-1][index].sa);
                    index++;
                }
                dp[i][j]=min(dp[i][j],mini+a[i][j].sa+a[i][j].sb);
            }
            index=n-1,mini=inf;
            for(int j=n-1;j>=0;j--)
            {
                while(index>=0&&a[i-1][index].sa>a[i][j].sa)
                {
                    mini=min(mini,dp[i-1][index]+a[i-1][index].sa);
                    index--;
                }
                dp[i][j]=min(dp[i][j],mini-a[i][j].sa+a[i][j].sb);
            }
        }
        int ans=inf;
        for(int i=0;i<n;i++)
            ans=min(ans,dp[m-1][i]);
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(dp)