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;
}