dp * 3

cf 467 C

从序列中选出 \(k\) 段连续的 \(m\) 个数
最大化总和
\(f_{i, j}\) 表示前 \(i\) 个位置中选出了 \(j\)
转移显然

#include <bits/stdc++.h>

const int N = 5010;

long long f[N][N];
int n, m, k;
long long Sum[N];

int main() {
	std:: cin >> n >> m >> k;
	for(int i = 1; i <= n; i ++) {
		std:: cin >> Sum[i];
		Sum[i] += Sum[i - 1];
	}
	for(int i = 1; i <= n; i ++) {
		for(int j = 1; j <= k; j ++) {
			if(i - m + 1 > 0) f[i][j] = f[i - m][j - 1] + Sum[i] - Sum[i - m];
			f[i][j] = std:: max(f[i - 1][j], f[i][j]);
		}
	}
	std:: cout << f[n][k];
	return 0;
}

51nod 1354

给出序列 \(a\) 和一个整数 \(k\)
求子序列的乘积是 \(k\) 的倍数的方案数

\(f_{i, j}\) 表示前 \(i\) 个数,乘积是 \(j\) 的方案数
\(f_{i, j} = f_{i - 1, \frac{j}{a_{i - 1}}} + f_{i - 1, j}\)

由于 \(k\) 很大
显然单纯的数组是无法完成的
这里可以使用 \(map\), 通过遍历完成

#include <bits/stdc++.h>

const int N = 1010, Mod = 1e9 + 7;

std:: map <int, int> Map[N];
int n, k, t;
int A[N];

int main() {
	std:: cin >> t;
	for(; t; t --) {
		std:: cin >> n >> k;
		Map[0].clear();
		for(int i = 1; i <= n; i ++) {
			std:: cin >> A[i];
			Map[i].clear();
		}
		Map[0][k] = 1;
		for(int i = 0; i < n; i ++)
			for(std:: map <int, int> :: iterator it = Map[i].begin(); it != Map[i].end(); it ++) {
				if(it-> first % A[i + 1] == 0)
					(Map[i + 1][it-> first / A[i + 1]] += it-> second) %= Mod;
				(Map[i + 1][it-> first] += it-> second) %= Mod;
			}
		std:: cout << Map[n][1] << "\n";
	}
	return 0;
}

openjudge 6047

\(w \times h\) 的蛋糕,切成 \(m\)
每刀可以将一块切成两块
求最小化的最大蛋糕面积
\(f_{i, j, k}\) 表示将 \(i \times j\) 的蛋糕切成 \(m\) 块时的最小化的最大蛋糕面积
枚举蛋糕的长和宽以及切成的块数
固定好后枚举长从哪里分割 \(h\) 以及分成的块数 \(p\)
\(f_{i, j, k} = min(f_{i, j, k}, max(f_{h, j, p}, f_{i - h, j, p}))\)
同理枚举列
\(f_{i, j, k} = min(f_{i, j, k}, max(f_{i, l, p}, f_{i, j - l, p}))\)

#include <bits/stdc++.h>

const int N = 25;

int f[N][N][N];

int main() {
	int w, h, m;
	while(std:: cin >> w >> h >> m) {
		memset(f, 0, sizeof f);
		if(w == 0 && h == 0 && m == 0) break;
		for(int i = 1; i <= w; i ++)
			for(int j = 1; j <= h; j ++)
				f[i][j][1] = i * j;
		for(int i = 1; i <= w; i ++)
			for(int j = 1; j <= h; j ++)
				for(int k = 2; k <= std:: min(i * j, m); k ++) {
					f[i][j][k] = (1 << 30);
					for(int H = 1; H < i; H ++)
						for(int p = 1; p < k; p ++)
							f[i][j][k] = std:: min(f[i][j][k], std:: max(f[H][j][p], f[i - H][j][k - p]));
					for(int L = 1; L < j; L ++)
						for(int p = 1; p < k; p ++)
							f[i][j][k] = std:: min(f[i][j][k], std:: max(f[i][L][p], f[i][j - L][k - p]));
				}
		std:: cout << f[w][h][m] << "\n";
	}
	return 0;
}
posted @ 2018-09-17 19:44  xayata  阅读(135)  评论(0编辑  收藏  举报