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('\n');
        Icase++;
        printf("Case %d:\n", Icase);
        if (Max == 1)
            printf("My king, at most %d road can be built.\n", Max);
        else
            printf("My king, at most %d roads can be built.\n", 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",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\n", ++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\n\n", 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("\n");
    }
}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\n", 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

 

posted on 2015-04-20 19:41  一个西瓜  阅读(350)  评论(0编辑  收藏  举报

导航