• MUTC7 C


    Dragon Ball

    Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 1680    Accepted Submission(s): 614


    Problem Description
    Sean has got a Treasure map which shows when and where the dragon balls will appear. some dragon balls will appear in a line at the same time for each period.Since the time you got one of them,the other dragon ball will disappear so he can only and must get one Dragon ball in each period.Digging out one ball he will lose some energy.Sean will lose |x-y| energy when he move from x to y.Suppose Sean has enough time to get any drogan ball he want in each period.We want to know the minimum energy sean will lose to get all period’s dragon ball.
     

    Input
    In the first line a number T indicate the number of test cases.Then for each case the first line contain 3 numbers m,n,x(1<=m<=50,1<=n<=1000),indicate m period Dragon ball will appear,n dragon balls for every period, x is the initial location of sean.Then two m*n matrix. For the first matrix,the number in I row and J column indicate the location of J-th Dragon ball in I th period.For the second matrix the number in I row and J column indicate the energy sean will lose for J-th Dragon ball in I-th period.
     

    Output
    For each case print a number means the minimum energy sean will lose.
     

    Sample Input
    1 3 2 5 2 3 4 1 1 3 1 1 1 3 4 2
     

    Sample Output
    8
     

    Author
    FZU
     

    Source
     

    Recommend
    zhuyuanchen520

    ------------

    单调队列+DP


    设dp[i][j]表示第i批龙珠中取第j个需要花费的最小体力。

    dp[i][j] = min{ dp[i-1][k] + abs(pos[i-1][k]-pos[i][j]) } + cost[i][j];

    如果枚举k的话总复杂度位m*n*n,会超时。

    可以看出若每个状态只由上一层位置在其左边的状态的转移而来的话:  

    dp[i][j]

    min { dp[i-1][k] + pos[i][j] - pos[i-1][k] } + cost[i][j]

    = min { dp[i-1][k] - pos[i-1][k] } + pos[i][j] + cost[i][j]

    dp[i-1][k]-pos[i-1][k]是个确定的值,就是相当于求位置在pos[i][j]左边的上一层状态中值最小的,可以用个单调队列维护。由右边转移来的类似,再处理一遍右边转移来的取最优。

    因为要对同一层的点排序,所以总复杂度是m*n*logn。

    -----------

    /** head-file **/
    
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <iomanip>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <list>
    #include <set>
    #include <map>
    #include <algorithm>
    
    /** define-for **/
    
    #define REP(i, n) for (int i=0;i<int(n);++i)
    #define FOR(i, a, b) for (int i=int(a);i<int(b);++i)
    #define DWN(i, b, a) for (int i=int(b-1);i>=int(a);--i)
    #define REP_1(i, n) for (int i=1;i<=int(n);++i)
    #define FOR_1(i, a, b) for (int i=int(a);i<=int(b);++i)
    #define DWN_1(i, b, a) for (int i=int(b);i>=int(a);--i)
    #define REP_N(i, n) for (i=0;i<int(n);++i)
    #define FOR_N(i, a, b) for (i=int(a);i<int(b);++i)
    #define DWN_N(i, b, a) for (i=int(b-1);i>=int(a);--i)
    #define REP_1_N(i, n) for (i=1;i<=int(n);++i)
    #define FOR_1_N(i, a, b) for (i=int(a);i<=int(b);++i)
    #define DWN_1_N(i, b, a) for (i=int(b);i>=int(a);--i)
    
    /** define-useful **/
    
    #define clr(x,a) memset(x,a,sizeof(x))
    #define sz(x) int(x.size())
    #define see(x) cerr<<#x<<" "<<x<<endl
    #define se(x) cerr<<" "<<x
    #define pb push_back
    #define mp make_pair
    
    /** test **/
    
    #define Display(A, n, m) {                      
        REP(i, n){                                  
            REP(j, m) cout << A[i][j] << " ";       
            cout << endl;                           
        }                                           
    }
    
    #define Display_1(A, n, m) {                    
        REP_1(i, n){                                
            REP_1(j, m) cout << A[i][j] << " ";     
            cout << endl;                           
        }                                           
    }
    
    using namespace std;
    
    /** typedef **/
    
    typedef long long LL;
    
    /** Add - On **/
    
    const int direct4[4][2]={ {0,1},{1,0},{0,-1},{-1,0} };
    const int direct8[8][2]={ {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
    const int direct3[6][3]={ {1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1} };
    
    const int MOD = 1000000007;
    const int INF = 0x3f3f3f3f;
    const long long INFF = 1LL << 60;
    const double EPS = 1e-9;
    const double OO = 1e15;
    const double PI = acos(-1.0); //M_PI;
    
    int n,m,s;
    struct node{
        int local;
        int cost;
    }a[55][1111];
    int f[55][1111];
    /** f[i][j]=min(f[i-1][k]+abs(a[i][j].local-a[i-1][k].local)+a[i][j].cost) **/
    int head,tail;
    int que[1111];
    int dp(int i,int j,int k)
    {
        return f[i-1][k]+abs(a[i][j].local-a[i-1][k].local)+a[i][j].cost;
    }
    
    bool cmp(node a,node b)
    {
        return a.local<b.local;
    }
    
    int main()
    {
        int T;
        cin>>T;
        while (cin>>n>>m>>s)
        {
            clr(f,INF);
            REP_1(i,n) REP_1(j,m)
                cin>>a[i][j].local;
            REP_1(i,n)
            {
                REP_1(j,m) cin>>a[i][j].cost;
                sort(a[i]+1,a[i]+m+1,cmp);
            }
            REP_1(i,m)
            {
                f[1][i]=abs(s-a[1][i].local)+a[1][i].cost;
            }
            FOR_1(i,2,n)
            {
                head=tail=0;
                int k=1;
                FOR_1(j,1,m)
                {
                    while (k<=m&&a[i-1][k].local<=a[i][j].local)
                    {
                        int t=dp(i,j,k);
                        while (head<tail&&dp(i,j,que[tail-1])>=t) tail--;
                        que[tail++]=k;
                        k++;
                    }
                    if (head<tail) f[i][j]=dp(i,j,que[head]);
                }
                head=tail=0;
                k=m;
                DWN_1(j,m,1)
                {
                    while (k>=1&&a[i-1][k].local>a[i][j].local)
                    {
                        int t=dp(i,j,k);
                        while (head<tail&&dp(i,j,que[tail-1])>=t) tail--;
                        que[tail++]=k;
                        k--;
                    }
                    if (head<tail) f[i][j]=min(f[i][j],dp(i,j,que[head]));
                }
            }
            int ans=INF;
            REP_1(i,m)
            {
                ans=min(ans,f[n][i]);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    




  • 相关阅读:
    操作系统进程
    Lowest Common Ancestor of a Binary Search Tree
    Java并发编程实践之对象的组合
    字典序排序-求全排列(元素有重复)
    计算机网络基础知识
    多线程的基础知识
    多线程编程题
    Flask安装
    appium使用实例
    调用Excel或Oracle数据,数据加载,selenium等使用实例
  • 原文地址:https://www.cnblogs.com/cyendra/p/3226275.html
Copyright © 2020-2023  润新知