您的位置:首页 > 其它

动态规划入门练习

2017-03-10 21:05 246 查看

动态规划入门专题

POJ 2533 Longest Ordered Subsequence

最长单调上升子序列

状态转移方程:d[i] = max{0, d[j] | j < i, a[j] < a[i]} + 1;

int main() {
int n, a
, d
;
while(cin >> n) {
for(int i = 0; i < n; ++i) {
cin >> a[i];
d[i] = 1;
}
int maxValue = 1;
for(int i = 1; i < n; ++i) {
for(int j = 0; j < i; ++j) {
if(a[j] < a[i]) d[i] = max(d[i], d[j]+1);
}
maxValue = max(d[i], maxValue);
}
cout << maxValue << endl;
}
return 0;
}


POJ 1088 - 滑雪

状态转移方程:d[x][y] = {max(d[x][y] , d[xi][yi]) | 0 < i < 4, h[xi][yi] > d[x][y]} ,其中(xi, yi)为从(x, y)向四个方向移动一格的坐标

//记忆化搜索
#include <stdio.h>
#include <string.h>

#define FOR(i, n) for(int i = 0; i < n; i++)
#define max(x, y) x > y ? x : y

const int N = 100;

int r, c;
int h[N+5][N+5];
int d[N+5][N+5];
int dir[4][2] = {{0,-1}, {0,1}, {-1,0}, {1,0}};

int check(int x, int y) {
return x < 0 || x >= r || y < 0 || y >= c;
}

int dfs(int x, int y) {
if(d[x][y] == -1) {
d[x][y] = 1;
FOR(i, 4) {
int x1 = x + dir[i][0], y1 = y + dir[i][1];
if(!check(x1, y1) && h[x1][y1] > h[x][y])
d[x][y] = max(d[x][y], dfs(x1, y1) + 1);
}
}
return d[x][y];
}

int main() {
int maxHigh;
while(scanf("%d%d", &r, &c) != EOF){
maxHigh = 0;
memset(h, 0, sizeof(h));
memset(d, -1, sizeof(d));
FOR(i, r) FOR(j, c) scanf("%d", &h[i][j]);
FOR(i, r) FOR(j, c) {
dfs(i, j);
maxHigh = max(maxHigh, d[i][j]);
}
printf("%d\n", maxHigh);
}
}


HDU 1421 - 搬寝室

对于a < b < c < d序列, 有(ab, cd)、(ac, bd)、(ad, bc)三种组合,可以推出(ab, cd)是最优的选择

状态转移方程:

dp
[k] = min(dp[n-1][k], dp[n-2][k-1] + (a[i-1] - a[i-2]) ^ 2) {k != n>>1};

if(n是偶数) dp
[n>>1] = dp[n-2][k-1] + (a[i-1] - a[i-2]) ^ 2

#define SQ(x) ((x) * (x))

using namespace std;
const int N = 1005;
int dp[N<<1]
;
int main() {
int n, k;
int a[N<<1];
while(cin >> n >> k) {
for(int i = 0; i < n; ++i) cin >> a[i];
sort(a, a+n);
dp[2][1] = SQ(a[1] - a[0]);
for(int i = 3; i <= n; ++i) {
for(int j = 1; j <= (i>>1); ++j){
dp[i][j] = min(dp[i-1][j], dp[i-2][j-1] + SQ(a[i-1] - a[i-2]));
}
if(~i&1) dp[i][i>>1] = dp[i-2][(i>>1)-1] + SQ(a[i-1] - a[i-2]);
}
cout << dp
[k] << endl;
}
return 0;
}


POJ 2247 - Humble Numbers

A number whose only prime factors are 2,3,5 or 7 is called a humble number. The sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 24, 25, 27, … shows the first 20 humble numbers.

状态转移方程:d[0] = 1, d
= min(d[p[0]] * 2, d[p[1]] * 3, d[p[2]] * 5, d[p[3]] * 5),其中p[i]表示序列中数的位置,对于丑数序列中的每一个数n, n * 2, n * 3, n * 5, n * 7也都属于丑数序列,注意去重,如2*3 = 3*2

const int N = 5842;
int d[N+5];
int p[4];
int k[4] = {2, 3, 5, 7};
int main() {
int n = N;
d[0] = 1;
while(n--) {
int minValue = d[p[0]] * k[0];
for(int i = 1; i < 4; ++i) {
int temp = d[p[i]] * k[i];
minValue = minValue > temp ? temp : minValue;
}
// remove repeat number
for(int i = 0; i < 4; ++i)
if(d[p[i]]*k[i] == minValue)
p[i]++;
d[N-n] = minValue;
}

while(scanf("%d", &n) != EOF) {
if(n == 0) break;
if(n % 10 == 1 && n % 100 != 11)
printf("The %dst humble number is %d.\n", n, d[n-1]);
else if(n % 10 == 2 && n % 100 != 12)
printf("The %dnd humble number is %d.\n", n, d[n-1]);
else if(n % 10 == 3 && n % 100 != 13)
printf("The %drd humble number is %d.\n", n, d[n-1]);
else
printf("The %dth humble number is %d.\n", n, d[n-1]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: