• The Last Puzzle ZOJ


    题目链接
    本题也是区间dp,贪心可证,每一次出发必定是从端点,否则必然有重复,不会是最小值,那我们可以设dpi,j,0/1,0代表从左端点出发,1代表从右端点,因为每次都是从端点出发,状态方程为
    dpi,j,0=min(dpi+1,j,0+d[i+1]-d[i], dpi+1,j,1+dp[j]-dp[i])分别表示from i to i+1 to j, from i to j to i+1
    dpi,j,1=min(dpi,j-1,1+d[j]-d[j-1], dpi,j-1,0+dp[j]-dp[i])分别表示from j to j-1 to i, from j to i to j-1

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) ((x)&(-x))
    typedef long long LL;
    typedef pair<int,int> pii;
    
    const int maxn = 205;
    const int INF = 0x3f3f3f3f;
    int dp[maxn][maxn][2], d[maxn], t[maxn], mov[maxn][maxn][2];
    
    void run_case() {
        int n;
        while(cin >> n) {
            for(int i = 1; i <= n; ++i) cin >> t[i];
            for(int i = 1; i <= n; ++i) cin >> d[i];
            memset(dp, 0, sizeof(dp));
            for(int i = n-1; i >= 1; --i) {
                for(int j = i+1; j <= n; ++j) {
                    
                    if(dp[i+1][j][0] + d[i+1] - d[i] < dp[i+1][j][1] + d[j] - d[i]) {
                        dp[i][j][0] = dp[i+1][j][0] + d[i+1] - d[i];
                        mov[i][j][0] = 0; // from i to i+1
                    } else {
                        dp[i][j][0] = dp[i+1][j][1] + d[j] - d[i];
                        mov[i][j][0] = 1; // from i to j
                    }
                    if(dp[i][j][0] >= t[i]) {
                        dp[i][j][0] = INF;
                    }
                    // calculate dp[i][j][1]
                    if(dp[i][j-1][0] + d[j] - d[i] < dp[i][j-1][1] + d[j] - d[j-1]) {
                        dp[i][j][1] = dp[i][j-1][0] + d[j] - d[i];
                        mov[i][j][1] = 0; // from j to i
                    } else {
                        dp[i][j][1] = dp[i][j-1][1] + d[j] - d[j-1];
                        mov[i][j][1] = 1; // from j to j-1
                    }
                    if(dp[i][j][1] >= t[j]) {
                        dp[i][j][1] = INF;
                    }
                }
            }
            int l=0, r=-1, flag;
            if(dp[1][n][0] < INF) {
                l = 2, r = n;
                flag = mov[1][n][0];
                cout << "1";
            } else if(dp[1][n][1] < INF) {
                l = 1, r = n-1;
                flag = mov[1][n][1];
                cout << n;
            } else {
                cout << "Mission Impossible";
            }
            while(l <= r) {
                if(flag) {
                    cout << " " << r;
                    flag = mov[l][r][1];
                    r--;
                } else {
                    cout << " " << l;
                    flag = mov[l][r][0];
                    l++;
                }
            }
            cout << "
    ";
        }
    }
    
    int main() {
        ios::sync_with_stdio(false), cin.tie(0);
        cout.flags(ios::fixed);cout.precision(10);
        //int t; cin >> t;
        run_case();
        cout.flush();
        return 0;
    }
    

    何时区间dp呢?

    数据范围一定
    需要维护区间状态,不同区间选择造成的影响不同,石子合并,杀狼等

  • 相关阅读:
    高效真实的云渲染算法 【转】
    网络字节顺序 【转】
    Windows网络编程 2 【转】
    windows 网络编程[转]
    电信诈骗
    winsock 收发广播包 【转】
    windows核心编程 DLL技术 【转】
    CityEngine结合ArcGIS制作地质体web场景 [转]
    共有49款Windows GUI开发框架开源软件 【转】
    详解分级基金(杠杆基金)【精华】 【转】
  • 原文地址:https://www.cnblogs.com/GRedComeT/p/12356169.html
Copyright © 2020-2023  润新知