zoukankan      html  css  js  c++  java
  • 《洛谷P1282 多米诺骨牌》

    好题!

    第一眼就感觉是dp。

    设dp[i][j]表示到第i个位置上面-下面为j的最小步数。

    可以发现,这里由于上面-下面可能是负的。

    那么单纯去dp显然不行。

    这里就用到了一个思想,零点转移。

    因为差距最多在5,6000左右,我们设6000为0点,那么-T就变成了6000-T。

    然后就可以去dp了,正负分开下判断即可。

    // Author: levil
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e3+5;
    const int M = 2e4+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    void FRE(){/*freopen("data1.in","r",stdin);
    freopen("data1.out","w",stdout);*/}
    
    int a[1005],b[1005],dp[N][12005];
    int main()
    {
        int n;n = read();
        for(int i = 1;i <= n;++i) a[i] = read(),b[i] = read();
        for(int i = 0;i <= n;++i)
            for(int j = 0;j <= 12005;++j) dp[i][j] = INF;
        dp[0][6000] = 0;
        for(int i = 1;i <= n;++i)
        {
            int dis = a[i]-b[i];
            if(dis >= 0)
            {
                for(int j = 12000;j >= 0;--j) if(j-dis >= 0) dp[i][j] = min(dp[i][j],dp[i-1][j-dis]);  
                dis = -dis;
                for(int j = 0;j <= 12000;++j) if(j-dis <= 12000) dp[i][j] = min(dp[i][j],dp[i-1][j-dis]+1);
            }
            else
            {
                for(int j = 0;j <= 12000;++j) if(j-dis <= 12000) dp[i][j] = min(dp[i][j],dp[i-1][j-dis]);
                dis = -dis;
                for(int j = 12000;j >= 0;--j) if(j-dis >= 0) dp[i][j] = min(dp[i][j],dp[i-1][j-dis]+1);
            }
        }
        int ans = INF,step;
        for(int i = 0;i <= 12000;++i) 
        {
            if((abs(i-6000) < ans && dp[n][i] != INF) || (abs(i-6000) == ans && dp[n][i] < step)) ans = abs(i-6000),step = dp[n][i];
        }
        printf("%d
    ",step);
        system("pause");    
    }
    View Code
  • 相关阅读:
    编译原理实验之SLR1文法分析
    机器学习中的特征选择filter
    按部就班的吴恩达机器学习网课用于讨论(4)
    Linux客户端网口输入转串口输出
    按部就班的吴恩达机器学习网课用于讨论(3)
    关于网络手动搭建的一点补充说明
    按部就班的吴恩达机器学习网课用于讨论(2)
    按部就班的吴恩达机器学习网课用于讨论(1)
    java学习与应用(5.3)--Spring
    java学习与应用(5.2)--Spring Boot 预告篇
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13664755.html
Copyright © 2011-2022 走看看