zoukankan      html  css  js  c++  java
  • 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] << "
    ";
    	}
    	return 0;
    }
    

    openjudge 6047

    (w imes h) 的蛋糕,切成 (m)
    每刀可以将一块切成两块
    求最小化的最大蛋糕面积
    (f_{i, j, k}) 表示将 (i imes 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] << "
    ";
    	}
    	return 0;
    }
    
  • 相关阅读:
    HOJ 2139 Spiderman's workout(动态规划)
    FZU 2107 Hua Rong Dao(dfs)
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 无向连通图最少包含多少条边
    Java 第十一届 蓝桥杯 省模拟赛 无向连通图最少包含多少条边
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9664416.html
Copyright © 2011-2022 走看看