• Dp46道和近期小结


    最近做题比较散漫,无脑。中间打了个校赛,弱弱的水了几题,然后就挂机了,最后一个半小时都在酱油,结果也不是很好。

    中间大概有三场bc是爆零了,快浅绿了。cf 打了两场只有only div2的,还好比较容易涨,大号终于紫了。

    Hdu Dp入门题总结,时间隔的比较长,大概有一个月了。。网上写的也比较详细,这6题还是记忆犹新的,其他的就不说了。

     Cstructing Roads http://acm.hdu.edu.cn/showproblem.php?pid=1025 

    以前做过,按照一维排序,另一位用nlogn的LIS做法做。写的时候,发现线段树可以搞,按照其中一维排序以后,

    在另一维上建树,每个点的值表示这个点之前的最多连线对包括这个点。更新的时候,找到这个点之前的最大值,然后

    最大值加一更新到这个点上。线段树维护一下区间最大值。

    /* ***********************************************
        Author        : 一个西瓜
        Mail          : 879447570@qq.com
        Created Time  : 2015-04-14 20:32:08
        Problem       : Constructing Roads In JGShining's Kingdom
        ************************************************ */
    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <map>
    #include <set>
    using namespace std;
    #define INF 1000000000
    //typedef __int64 LL; 
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    
    const int maxn = 555555 + 10;
    int sum[maxn << 2];
    void build(int l, int r, int rt)
    {
        sum[rt] = 0;
        if (l == r) return;
        int mid = (l + r) >> 1;
        build(lson); build(rson);
    }
    void up(int rt)
    {
        sum[rt] = max(sum[rt << 1], sum[rt << 1 | 1]);
    }
    
    void update(int key, int add, int l, int r, int rt)
    {
        if (l == r){
            sum[rt] = add; return;
        }
        int mid = (l + r) >> 1;
        if (key <= mid) update(key, add, lson);
        else update(key, add, rson);
        up(rt);
    }
    
    int ask(int L, int R, int l, int r, int rt)
    {
        if (L <= l&&r <= R) return sum[rt];
        int ans = -1;
        int mid = (l + r) >> 1;
        if (L <= mid) ans = max(ans, ask(L, R, lson));
        if (R > mid) ans = max(ans, ask(L, R, rson));
        return ans;
    }
    
    struct Node
    {
        int x; int y;
    }node[maxn];
    
    int cmp(const Node &a, const Node &b)
    {
        if (a.x == b.x) return a.y < b.y;
        return a.x < b.x;
    }
    
    int main()
    {
        int n;
        int Icase = 0;
        while (cin >> n){
            build(1, n, 1);
            for (int i = 1; i <= n; i++) scanf("%d%d", &node[i].x, &node[i].y);
            int Max = -1;
            sort(node + 1, node + 1 + n, cmp);
            for (int i = 1; i <= n; i++){
                int t = ask(1, node[i].y, 1, n, 1);
                Max = max(Max, t + 1);
                update(node[i].y, t + 1, 1, n, 1);
            }
            //if (Icase) putchar('
    ');
            Icase++;
            printf("Case %d:
    ", Icase);
            if (Max == 1)
                printf("My king, at most %d road can be built.
    ", Max);
            else
                printf("My king, at most %d roads can be built.
    ", Max);
            cout << endl;
        }
        return 0;
    }
    View Code

    Humble Numbers http://acm.hdu.edu.cn/showproblem.php?pid=1058 

    dp[n] = min(2*dp[i],3*dp[j],5*dp[k],7*dp[l]; 哪个最小, 哪个下标加一

    /* ***********************************************
    Author        : wtmlon
    Mail          : 879447570@qq.com
    Created Time  : 2015-03-27 19:42:09
    Problem       : Humble Numbers
    ************************************************ */
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <map>
    #include <set>
    using namespace std;
    #define INF 1000000000
    //typedef __int64 LL; 
    
    int f[111111];
    int Min(int a, int b, int c, int d)
    {
        return min(min(a, b), min(c, d));
    }
    int gao(int a, int b, int c, int d)
    {
        int a1 = f[a] * 2; int b1 = f[b] * 3; int c1 = f[c] * 5; int d1 = f[d] * 7;
        int t = Min(a1, b1, c1, d1);
        if (t == a1) return 1;
        if (t == b1) return 2;
        if (t == c1) return 3;
        return 4;
    }
    
    int main()
    {
        int n;
        int  l2 = 1, l3 = 1, l5 = 1, l7 = 1;
        f[1] = 1;
        for (int i = 2; i <= 5842; i++){
            int t = gao(l2, l3, l5, l7);
            if (t == 1){
                int k = f[l2] * 2;
                if (k == f[i - 1]) {
                    i--; l2++; continue;
                }
                f[i] = k; l2++;
            }
            if (t == 2){
                int k = f[l3] * 3;
                if (k == f[i - 1]){
                    i--; l3++; continue;
                }
                f[i] = k; l3++;
            }
            if (t == 3){
                int k = f[l5] * 5;
                if (k == f[i - 1]){
                    i--; l5++; continue;
                }
                f[i] = k; l5++;
            }
            if (t == 4){
                int k = f[l7] * 7;
                if (k == f[i - 1]){
                    i--; l7++; continue;
                }
                f[i] = k; l7++;
            }
        }
        while (cin >> n&&n){
            int k = n%100;
            if(k>=10&&k<=20){
                printf("The %dth humble number is %d.
    ",n,f[n]);
            }
            else{
                k = k%10;
                if(k==1){
                    printf("The %dst humble number is %d.",n,f[n]);
                }
                else if(k==2){
                    printf("The %dnd humble number is %d.",n,f[n]);
                }
                else if(k==3){
                    printf("The %drd humble number is %d.",n,f[n]);
                }
                else printf("The %dth humble number is %d.",n,f[n]);
                cout<<endl;
            }
        }
        return 0;
    }
    View Code

    Fast Food http://acm.hdu.edu.cn/showproblem.php?pid=1227

    搜的题解发现中位数距离最短,然后就能写了。顺便学了下带权中位数,就是一样的,把权值当成个数,然后按照大小排序过以后,权值从头开始加找到恰好大于所有权值和w的一半时的那个点,这个点到其他所有点的带权曼哈顿距离和最小。可以求多维的情况,因为是曼哈顿距离,所以不同维度的距离和是相互独立的。

    /* ***********************************************
    Author        : 一个西瓜
    Mail          : 879447570@qq.com
    Created Time  : 2015-04-19 14:47:52
    Problem       : Fast Food
    ************************************************ */
    
    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <map>
    #include <set>
    using namespace std;
    #define INF 1000000000
    //typedef __int64 LL; 
    
    int a[222];
    int sum[222];
    int dp[222][222];
    
    int cost(int x, int y)
    {
        int t = (x + y) / 2;
        int ans = 0;
        for (int i = x; i <= y; i++){
            ans += abs(a[i] - a[t]);
        }
        return ans;
    }
    
    int main()
    {
        int Icase = 0;
        int n, k;
        while (cin >> n >> k, n || k){
            for (int i = 1; i <= n; i++){
                scanf("%d", &a[i]);
            }
            printf("Chain %d
    ", ++Icase);
            for (int i = 1; i <= n;i++)
            for (int j = 1; j <= k; j++) dp[i][j] = INF;
            /*for (int i = 1; i <= n; i++){
                for (int j = i + 1; j <= n; j++){
                    int ans = 0;
                    for (int k = i + 1; k < j; k++){
                        ans += min(a[k] - a[i], a[j] - a[k]);
                    }
                    cost[i][j] = ans;
                }
            }*/
            /*for (int i = 1; i <= n; i++){
                int ans = 0;
                for (int j = 1; j < i; j++){
                    ans += a[i] - a[j];
                }
                dp[i][1] = ans;
            }*/
            for (int i = 1; i <= n; i++) dp[i][1] = cost(1, i);
            for (int i = 2; i <= k; i++){
                for (int j = 1; j <= n; j++){
                    for (int l = i - 1; l < j; l++){
                        dp[j][i] = min(dp[j][i], dp[l][i - 1] + cost(l+1,j));
                    }
                }
            }
            printf("Total distance sum = %d
    
    ", dp[n][k]);
        }
        return 0;
    }
    View Code

    Regular Words http://acm.hdu.edu.cn/showproblem.php?pid=1502

    抄了个大数模板卡过, dp[i][j][k] = dp[i-1][j][k] + dp[i][j-1][k] + dp[i][j][k-1];

    /* ***********************************************
    Author        : 一个西瓜
    Mail          : 879447570@qq.com
    Created Time  : 2015-04-20 10:12:04
    Problem       : Regular Words
    ************************************************ */
    
    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <map>
    #include <set>
    using namespace std;
    #define INF 1000000000
    //typedef __int64 LL; 
    typedef long long LL;
    //套了个大数模板卡过。
    
    struct BigInt {
        const static int mod = 10000;
        const static int DLEN = 4;
        int a[30], len;
        BigInt() {
            memset(a, 0, sizeof(a));
            len = 1;
        }
        BigInt(int v) {
            memset(a, 0, sizeof(a));
            len = 0;
            do
            {
                a[len++] = v%mod;
                v /= mod;
            } while (v);
        }
        BigInt(const char s[]) {
            memset(a, 0, sizeof(a));
            int L = strlen(s);
            len = L / DLEN;
            if (L%DLEN)len++;
            int index = 0;
            for (int i = L - 1; i >= 0; i -= DLEN) {
                int t = 0;
                int k = i - DLEN + 1;
                if (k < 0)k = 0;
                for (int j = k; j <= i; j++)
                    t = t * 10 + s[j] - '0';
                a[index++] = t;
            }
        }
        BigInt operator +(const BigInt &b)const {
            BigInt res;
            res.len = max(len, b.len);
            for (int i = 0; i <= res.len; i++)
                res.a[i] = 0;
            for (int i = 0; i < res.len; i++) {
                res.a[i] += ((i < len) ? a[i] : 0) + ((i < b.len) ? b.a[i] : 0);
                res.a[i + 1] += res.a[i] / mod;
                res.a[i] %= mod;
            }
            if (res.a[res.len] > 0)res.len++;
            return res;
        }
        BigInt operator *(const BigInt &b)const {
            BigInt res;
            for (int i = 0; i < len; i++) {
                int up = 0;
                for (int j = 0; j < b.len; j++) {
                    int temp = a[i] * b.a[j] + res.a[i + j] + up;
                    res.a[i + j] = temp%mod;
                    up = temp / mod;
                }
                if (up != 0)
                    res.a[i + b.len] = up;
            }
            res.len = len + b.len;
            while (res.a[res.len - 1] == 0 && res.len > 1)res.len--;
            return res;
        }
        void output() {
            printf("%d", a[len - 1]);
            for (int i = len - 2; i >= 0; i--)
                printf("%04d", a[i]);
            printf("
    ");
        }
    }dp[61][61][61];
    int main()
    {
        int n;
        BigInt gg(1);
        dp[0][0][0] = dp[0][0][0] + gg;
        for (int i = 1; i <= 60; i++){
            for (int j = 0; j <= i; j++){
                for (int k = 0; k <= j; k++){
                    if (i - 1 >= j) dp[i][j][k] =dp[i][j][k] + dp[i - 1][j][k];
                    if (j - 1 >= k) dp[i][j][k] =dp[i][j][k] + dp[i][j - 1][k];
                    if (k - 1 >= 0) dp[i][j][k] =dp[i][j][k] + dp[i][j][k - 1];
                }
            }
        }
        while (cin >> n){
            dp[n][n][n].output();
            cout << endl;
        }
        return 0;
    }
    View Code

    Doing Homework Again http://acm.hdu.edu.cn/showproblem.php?pid=1789 

    按截止日期从小到大排个序,然后dp[i][j] 表示第i个任务当前时间为j的最多得的分

    dp[i][j] = max(dp[i-1][j] , dp[i-1][j-1] + val[i]); j这天做不做第i个任务中间的最多得分.

    拿总的分数减下,就是最少的要扣的分数。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <map>
    #include <set>
    using namespace std;
    #define INF 1000000000
    //typedef __int64 LL;
    const int maxn = 1111;
    struct Node
    {
        int x; int y;
    }node[maxn];
    
    int cmp(const Node &a, const Node &b)
    {
        if (a.x == b.x) return a.y < b.y; 
        return a.x < b.x;
    }
    int dp[maxn][maxn];
    
    int main()
    {
        int T,n;
        cin >> T;
        while (T--){
            cin >> n;
            int sum = 0; int Max = -1;
            for (int i = 1; i <= n; i++) scanf("%d", &node[i].x);
            for (int i = 1; i <= n; i++) scanf("%d", &node[i].y), sum += node[i].y;
            sort(node + 1, node + 1 + n, cmp);
            memset(dp,0,sizeof(dp));
            for (int i = 1; i <= n; i++){
                for (int j = 1; j <= node[i].x; j++){
                    dp[i][j] = max(dp[i - 1][j - 1] + node[i].y, dp[i - 1][j]);
                    Max = max(dp[i][j], Max);
                }
            }
            cout << sum - Max << endl;
        }
        return 0;
    }
    View Code

    Employment Planning http://acm.hdu.edu.cn/showproblem.php?pid=1158 

    我猜测能雇佣人数的取值范围就是每个月要求的人数的取值,所以最后就是一个n^2的dp,然后就过了。

    /* ***********************************************
    Author        : 一个西瓜
    Mail          : 879447570@qq.com
    Created Time  : 2015-04-15 20:53:26
    Problem       : Employment Plannin
    ************************************************ */
    
    #define _CRT_SECURE_NO_WARNINGS
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <cmath>
    #include <queue>
    #include <map>
    #include <set>
    using namespace std;
    #define INF 1000000000
    //typedef __int64 LL; 
    int a[100];
    int dp[30][30];
    int main()
    {
        int n;
        int hire, salary, fire;
        while (scanf("%d", &n) && n){
            scanf("%d%d%d", &hire, &salary, &fire);
            for (int i = 0; i <= n; i++)
            for (int j = 0; j <= n; j++)
                dp[i][j] = INF;
            dp[0][0] = 0;
            a[0] = 0;
            int Min = INF;
            for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
            for (int i = 1; i <= n; i++){
                for (int j = 0; j <= n; j++){
                    if (a[j] < a[i]) continue;
                    for (int k = 0; k <= n; k++){
                        int b = a[j]; int c = a[k];
                        if (b >= c){
                            dp[i][j] = min(dp[i][j], dp[i - 1][k] + b*salary + (b - c)*hire);
                        }
                        else{
                            dp[i][j] = min(dp[i][j], dp[i - 1][k] + (c - b)*fire + b*salary);
                        }
                        //if (i == 2 && j == 2) printf("%d %d %d %djiji
    ", b,c,dp[i][j],dp[i-1][]);
                    }
                    //cout << i << " " << j << " " << dp[i][j] << endl;
                }
            }
            for (int i = 1; i <= n; i++) Min = min(Min, dp[n][i]);
            cout << Min << endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Java 9 揭秘(9. 打破模块封装)
    Java 9 揭秘(8. JDK 9重大改变)
    好书分享 ——《深度工作》
    Java 9 揭秘(7. 创建自定义运行时映像)
    Java 9 揭秘(6. 封装模块)
    如何更好地管理你的精力,时间和专注力实现最佳表现
    这是您一直期待的所有iOS 11功能的屏幕截图
    我为什么不敢也不想写自己的经验和想法?
    无聊? 现在你知道为什么了!
    Java 9 揭秘(5. 实现服务)
  • 原文地址:https://www.cnblogs.com/yigexigua/p/4441212.html
Copyright © 2020-2023  润新知