POJ #1050 1088 1141 1732 (dp初步练习)

POJ 1050 To the Max:

最大子矩阵和问题,枚举行数,将两行之间的元素纵向压缩为一维数组,然后求最大子区间和。

动态规划部分时间复杂度O(n^3),空间复杂度优化后O(n),用于保存压缩后的一维数组。

#define UVa  "poj-1050.cpp"		//To the Max
char fileIn[30] = UVa, fileOut[30] = UVa;

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<time.h>

using namespace std;

//Global Variables. Reset upon Each Case!
const int maxn = 100 + 5;
int n, m[maxn][maxn];
/

int maxSubInterval(int* ary, int len) {
    int ans = 0, dp = 0;
    for(int i = 0; i < len; i ++) {
        ans = max(ans, dp);
        if(dp > 0) dp = dp + ary[i];
        else dp = ary[i];
    }
    return ans;
}

int solve() {
    int b[maxn], ans = -(1<<30);
    for(int i = 0; i < n; i ++) {
        memset(b, 0, sizeof(b));
        for(int j = i; j < n; j ++) {
            for(int k = 0; k < n; k ++) {
                b[k] = b[k] + m[j][k];
            }
            if(maxSubInterval(b, n) > ans) {
                ans = max(ans, maxSubInterval(b, n));
            }
        }
    }
    return ans;
}

int main() {
    while(scanf("%d", &n) != EOF) {
        for(int i = 0; i < n; i ++)
            for(int j = 0; j < n; j ++)
                scanf("%d", &m[i][j]);
        cout<<solve()<<endl;
    }
    return 0;
}



POJ 1088 滑雪:

白书中的习题

#define UVa  "poj-1088.cpp"		//Hua Xue
char fileIn[30] = UVa, fileOut[30] = UVa;

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<iostream>

#include<map>
#include<queue>
#include<set>

#include<cstdlib>
#include<cmath>
#include<ctime>
#include<sstream>
#include<string>
#include<stack>
#include<ctype.h>

using namespace std;


//Global Variables. Reset upon Each Case!
const int maxn = 100 + 5;
int r, c, m[maxn][maxn];
int d[maxn][maxn];
const int step[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
/

int inside(int a, int b) {
    if(a < 0 || b < 0 || a >= r || b >= c) return 0;
    return 1;
}

int dp(int a, int b) {
    int& ans = d[a][b];
    if(ans != -1) return ans;
    ans = 1;
    for(int i = 0; i < 4; i ++) {
        int va = a + step[i][0], vb = b + step[i][1];
        if(!inside(va, vb)) continue;
        if(m[va][vb] < m[a][b]) {
            ans = max(ans, dp(va, vb) + 1);
        }
    }
    return ans;
}

int main() {
    while(scanf("%d%d", &r, &c) != EOF) {
        memset(d, -1, sizeof(d));
        for(int i = 0; i < r; i ++)
            for(int j = 0; j < c; j ++)
                scanf("%d", &m[i][j]);
        int ans = 0;
        for(int i = 0; i < r; i ++)
            for(int j = 0; j < c; j ++)
                ans = max(ans, dp(i, j));
        printf("%d\n", ans);

    }
    return 0;
}




POJ 1141 Brackets Sequence:

线性结构dp,白书中的例题。两次dp,第二次用于打印解。注意空序列陷阱。

#define UVa  "poj-1141.cpp"		//Brackets Sequence
char fileIn[30] = UVa, fileOut[30] = UVa;

#include<cstring>
#include<cstdio>
#include<algorithm>

using namespace std;

//Global Variables. Reset upon Each Case!
const int maxn = 100 + 10, INF = 1<<30;
char line[maxn];
int d[maxn][maxn];
/

int match(int a, int b) {
    if((line[a] == '(' && line[b] == ')') || (line[a] == '[' && line[b] == ']'))
        return 1;
    return 0;
}

int dp(int l, int r) {
    int& ans = d[l][r];
    if(ans != -1) return ans;
    if(l == r) {
        return ans = 1;
    }
    ans = INF;
    if(match(l, r)) {
        if(l == r-1) {
            return ans = 0;
        }
        ans = min(ans, dp(l+1, r-1));
    }
    for(int i = l; i < r; i ++) {
        ans = min(ans, dp(l, i) + dp(i+1, r));
    }
    return ans;
}

void print_comb(char ch) {
    if(ch == '(' || ch == ')') printf("()");
    if(ch == '[' || ch == ']') printf("[]");
}

void print_ans(int l, int r) {
    if(l > r) return;
    if(l == r) {
        print_comb(line[l]);
        return;
    }
    if(match(l, r)) {
        if(l == r-1) {
            printf("%c%c", line[l], line[r]);
            return;
        }
        if(d[l+1][r-1] == d[l][r]) {
            printf("%c",line[l]);
            print_ans(l+1, r-1);
            printf("%c",line[r]);
            return;
        }
    }
    for(int i = l; i < r; i ++) {
        if(d[l][r] == d[l][i] + d[i+1][r]) {
            print_ans(l, i);
            print_ans(i+1, r);
            return;
        }
    }
}

int main() {
    while(gets(line) != NULL) {
        memset(d, -1, sizeof(d));
        dp(0, strlen(line)-1);
        print_ans(0, strlen(line)-1);
        printf("\n");
    }

    return 0;
}


POJ 1732 Phone numbers:

线型结构dp,刷表法。

#define UVa  "poj-1732.cpp"		//Phone numbers
char fileIn[30] = UVa, fileOut[30] = UVa;

#include<cstring>
#include<cstdio>
#include<algorithm>

using namespace std;


//Global Variables. Reset upon Each Case!
const int maxlen = 100 + 5, maxdict = 50000+5;
char line[maxlen], dict[maxdict][maxlen];
int num[200];
int n, m;
int d[maxlen], ans[maxlen];
/

void update(int& targ, int src, int& w, int tw) {
    if(targ == -1 || src < targ) {
        targ = src;
        w = tw;
    }
}


int match(int i, int p) {
    for(int j = 0; j < strlen(dict[i]); j ++)      //matching
        if(num[dict[i][j]] != line[p+j]-'0') return 0;
    return 1;
}

void print_ans(int i) {
    if(i == 0) return;
    int& w = ans[i];
    print_ans(i - strlen(dict[w]));
    printf("%s", dict[w]);
    if(i != n) printf(" ");
}

int main() {
    num['i'] = num['j'] = 1;    num['a'] = num['b'] = num['c'] = 2;    num['d'] = num['e'] = num['f'] = 3;    num['g'] = num['h'] = 4;    num['k'] = num['l'] = 5;    num['m'] = num['n'] = 6;    num['p'] = num['r'] = num['s'] = 7;    num['t'] = num['u'] = num['v'] = 8;    num['w'] = num['x'] = num['y'] = 9;    num['o'] = num['q'] = num['z'] = 0;

    while(scanf("%s", line) != EOF) {
        n = strlen(line);
        scanf("%d", &m);
        for(int i = 0; i < m; i ++)
            scanf("%s", &dict[i]);

        memset(d, -1, sizeof(d));
        d[0] = 0;
        for(int p = 0; p < n; p ++) {
            int& u = d[p];
            if(u == -1) continue;
            for(int i = 0; i < m; i ++) {       //iteraing all words
                int& v = d[p + strlen(dict[i])], &w = ans[p + strlen(dict[i])];
                if(match(i, p)) {
                    update(v, u+1, w, i);
                }
            }
        }
        if(d[n] == -1) printf("No solution.\n");
        else print_ans(n);

    }

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值