acm-DP整理
一、背包
.各种01背包
void leastOne_Pack(int id, int num ) {//至少取一个;
int i, j, c, v ;
for(i = ; i <= num ; i ++ )
{
scanf("%d %d", &c, &v) ;
for(j = T ; j >= c ; j -- )
{// 下面的顺序不能交换;
if(f[id][j-c] != - ) f[id][j] = getMax(f[id][j], f[id][j-c] + v ) ;
if(f[id-][j-c] != - ) f[id][j] = getMax(f[id][j], f[id-][j-c] + v ) ;
}
}
}
void mostOne_Pack(int id, int num ) { // 最多取一个;
int i, j ;
int c[N], v[N] ;
for(i = ; i <= num ; i ++ ) scanf("%d %d", &c[i], &v[i] ) ;
for(i = ; i <= T ; i ++ ) f[id][i] = f[id-][i] ;
for(i = ; i <= num ; i ++ )
{
for(j = T ; j >= c[i] ; j --)
if(j >= c[i] && f[id-][j-c[i]] != - ) f[id][j] = getMax(f[id][j], f[id-][j-c[i]] + v[i] ) ;
}
}
void common_Pack(int id, int num ){ // 一般的01背包;
int i, j, c, v ;
for(i = ; i <= T ; i ++ ) f[id][i] = f[id-][i] ;
for(i = ; i <= num ; i ++ )
{
scanf("%d %d", &c, &v) ;
for(j = T ; j >= c ; j -- )
if(f[id][j-c] != - ) f[id][j] = getMax(f[id][j], f[id][j-c] + v ) ;
}
}
.完全背包
void Comlepte_Pack(){
for(i = ; i < n ; i ++ )
{
scanf("%d %d", &p, &w ) ;
for(j = w ; j <= vol ; j ++ )
f[j] = f[j] < f[j-w] + p ? f[j] : f[j-w] + p ;
}
}
.依赖背包
struct Goods{
int c, v ;
} g[][] ;
void dependent_Pack(int vol, int gn ){
int i, j, k, mc, mv, c, v ;
for(j = , f[] = ; j <= vol ; j ++ ) f[j] = - ;
for(i = ; i <= gn ; i ++ )
{
if( !num[i]) continue ;
mc = g[i][].c ; mv = g[i][].v*mc ;
for(j = , h[] = ; j <= vol-mc ; j++ ) h[j] = - ;
for(k = ; k < num[i] ; k ++ )//10背包,相当于得到0 - vol-mc种物品;
{
c = g[i][k].c ; v = g[i][k].v*c ;
for(j = vol-mc ; j >= c ; j -- )
if(h[j-c] != - ) h[j] = h[j] > h[j-c]+v ? h[j] : h[j-c]+v ;
}
for(j = vol ; j >= mc ; j -- )//对于1 - vol-mc种物品,至多选择一种;
{
for(k = ; k <= j-mc ; k ++ )
{
if(h[k] == - ) continue ;
c = k+mc ; v = h[k]+mv ;
if(j >= c && f[j-c] != - ) f[j] = f[j] > f[j-c]+v ? f[j] : f[j-c]+v ;
}
}
}
}
二、极大化
.极大化算法一
以障碍点经过的边作为矩形的左边界,一直向右边扫描
struct Point{
int x, y ;
}p[MAXN] ;
bool comp(Point a, Point b){
if(a.x == b.x) return a.y < b.y ;
else return a.x < b.x ;
}
int DP(){// h,d 表示扫描线的上下端点高度
int i, j, h, d, s ;
int ans = ;
for (i = ; i <= n; i ++) //枚举障碍点
{
h = W ; d = ;
for(j = i+ ; j <= n && h > d ; j ++)
{
if(p[i].x == p[j].x || p[j].y > h || p[j].y < d) continue ;
// 扫描得到的矩形一定要经过i点
s = (h-d)*(p[j].x-p[i].x) ;
ans = ans > s ? ans : s ;
if(p[j].y < h && p[j].y >= p[i].y) h = p[j].y ;
//保证向前扫描一定经过i点
if(p[j].y > d && p[j].y <= p[i].y) d = p[j].y ;
}
}
return ans ;
}
int solve(){
int i, j, tx, ans = ;
while(~scanf("%d %d", &L, &W))
{
scanf("%d", &n) ; memset(pre, , sizeof(pre)) ;
for(i = ; i <= n ; i ++)
{
scanf("%d %d", &p[i].x, &p[i].y) ; pre[p[i].y] = ;
}
for(tx = , i = ; i <= W ; i ++)
{
tx ++ ;
if(pre[i])
{
ans = ans > tx ? ans : tx ;
tx = ;
}
}
ans = ans*L ;
p[++n].x = ; p[n].y = ; p[++n].x = ; p[n].y = W ;
p[++n].x = L ; p[n].y = ; p[++n].x = L ; p[n].y = W ;
sort(p+, p++n, comp) ;
tx = DP() ; printf("%d\n", ans > tx ? ans : tx) ;
}
} .算法二
a.悬线的定义:上端点是障碍点或者边界的线段 ;
() h[i][j]表示以点(i,j)结束的悬线的最大长度;
() l[i][j]表示悬线(i,j)左移量,r[i][j]表示其右移量;
() ml[i][j]表示点(i,j)左边最近的障碍点位置,没有时为左边界。同理……
b.dp方程:
() 如果点(i-,j)为障碍点或边界(i=):
h[i][j] = ,l[i][j] = L(大矩形长度),r[i][j] = ;
() 如果点(i-,j)不为障碍点:
h[i][j]=h[i-][j]+,
l[i][j]=max(l[i-][j],ml[i][j]),
r[i][j]=min(r[i-][j],mr[i][j]).
description :取最大周长矩形,该矩形要么由一种颜色覆盖,要么由两种颜色交叉覆盖。
int h[][MAXN][MAXN], l[][MAXN][MAXN], r[][MAXN][MAXN] ;
int mr[][MAXN][MAXN], ml[][MAXN][MAXN] ;
//[i][j] 左右边最近的异色点,没有异色点为边界位置
int map[MAXN][MAXN] ;
void getTable(){//初始化数组
int i, j ;
for(i = ; i <= n ; i ++)
{
map[i][] = map[i][] ; map[i][m+] = map[i][m] ;
ml[][i][] = ; mr[][i][m+] = m+ ;
for(j = ; j <= m ; j ++)
{
ml[][i][j] = ml[][i][j] =
(map[i][j]==map[i][j-]) ? ml[][i][j-] : j- ;
ml[][i][j] =
(map[i][j]^map[i][j-]) ? ml[][i][j-] : j- ;
}
for(j = m ; j ; j --)
{
mr[][i][j] = mr[][i][j] =
(map[i][j]==map[i][j+]) ? mr[][i][j+] : j+ ;
mr[][i][j] =
(map[i][j]^map[i][j+]) ? mr[][i][j+] : j+ ;
}
}
}
int DP(){
int i, j, k, ans = ;
for (i = ; i <= n ; i ++)
for (j = ; j <= m ; j ++)
{
for(k = ; k < ; k ++)
{
if(k < && (map[i][j] != k)) continue ;
bool v = map[i][j]^map[i-][j] ;
if(i == || ((-k) && v) || (!(-k) && !v) ) //特判
{
h[k][i][j] = ;
l[k][i][j] = ml[k][i][j] ;
r[k][i][j] = mr[k][i][j] ;
}
else {
h[k][i][j] = h[k][i-][j]+ ;
l[k][i][j] = max(l[k][i-][j], ml[k][i][j]) ;
r[k][i][j] = min(r[k][i-][j], mr[k][i][j]) ;
}
ans = max(ans, *(r[k][i][j]-l[k][i][j]-+h[k][i][j])) ;
}
}
return ans ;
}
int solve(){
getTable() ; printf("Case #%d: %d\n", cas ++, DP()) ;
}
三、分数规划
.二分法
double DP(double f){
int i ;
double ans ;
for(i = ; i <= n ; i ++) d[i] = 1.0*a[i] - b[i]*f;
sum[] = 0.0 ;
for(i = ; i <= n ; i ++) sum[i] = sum[i-] + d[i] ;
ans = sum[k] ; dp[k] = sum[k] ;
for(i = k+ ; i <= n ; i ++)
{
dp[i] = max(sum[i]-sum[i-k], dp[i-]+d[i]) ;
ans = max(ans, dp[i]) ;
}
return ans ;
}
double binary(double l, double r){
double mid ;
while(r-l > EPS)
{
mid = (l+r)/2.0 ;
if(DP(mid) > EPS) l = mid+EPS ;
else r = mid ;
}
return l ;
}
.牛顿逼近法
void build(double s){
int i, j ;
for(i = ; i <= n ; i ++)
for(j = ; j <= n ; j ++)
{
map[i][j].d = map[i][j].l - s*map[i][j].c ;
}
}
double solve(){
int i ;
double s, ans = 1.0 ;
do {
s = ans ;
build(s) ;
ans = kruskal() ;
}while(fabs(ans-s) > EPS) ;
return 1.0/ans ;
}
四、经典模型
.LICS平方算法
int dp[MAXN][MAXN] ; // dp[i][j]表示a[1-i]到b[1-j]且以b[j]结尾的LCIS ;
int dp_LCIS(){
int i, j, max_l , ans = ;
for(i = ; i <= m ; i ++) dp[][i] = ;
for(i = ; i <= n ; i ++)
{
max_l = ;
for(j = ; j <= m ; j ++)
{
dp[i][j] = dp[i-][j] ;
if(a[i] > b[j]) max_l = max(max_l, dp[i-][j]) ;
//因为相当于a[i] > b[k]与b[j] > b[k]等价( >= 是非递减);
if(a[i] == b[j]) dp[i][j] = max_l + ;
}
ans = max(ans, dp[i][m]) ;
}
return ans ;
}
.最长回文序列
int solve(){ //最长回文子序列
int i, j, tmp ;
memset(dp, , sizeof(dp)) ;
for(i = ; i <= *n ; i ++) dp[i][i] = ;
for(i = *n- ; i ; i --)
{
for(j = i+ ; j <= *n ; j ++)
{
dp[i][j] = max(dp[i+][j], dp[i][j-]) ;
tmp = dp[i+][j-] + *(ar[i] == ar[j]) ;
dp[i][j] = max(dp[i][j], tmp) ;
}
}
int ans = ;
for(i = n+ ; i <= *n ; i ++) ans = max(ans, dp[i-n+][i+n-]) ;
return ans ;
}
.最短编辑距离
int solve(){//最短编辑距离
int i, j, tmp, mx = max(ls, lt) ;
for(i = ; i <= ls ; i ++)
for(j = ; j <= lt ; j ++) dp[i][j] = mx ;
for(i = ; i <= mx ; i ++) dp[i][] = dp[][i] = i ;
for(i = ; i <= ls ; i ++ )
{
for(j = ; j <= lt ; j ++)
{
tmp = min(dp[i-][j]+, dp[i][j-]+) ;
if(s[i] == t[j]) dp[i][j] = min(dp[i][j], min(dp[i-][j-], tmp )) ;
else dp[i][j] = min(dp[i][j], min(tmp, dp[i-][j-] + )) ;
}
}
for(i = ; i <= ls ; i ++) printf("%d ", dp[i][lt]) ; puts("") ;
return dp[ls][lt] ;
}
.最长公共子序列个数
bool solve(){//最长公共子序列个数
int i, j ; bool d = ;
memset(f[d], , sizeof(f[d])) ; memset(g[d], , sizeof(g[d])) ;
for(i = max(n, m) ; i >= ; i --) g[d][i] = ;
for(i = ; i <= n ; i ++)
{
memset(f[!d], , sizeof(f[!d])) ; memset(g[!d], , sizeof(g[!d])) ;
g[!d][] = ;
for(j = ; j <= m ; j ++)
{
if(s[i] == t[j])
{
f[!d][j] = f[d][j-] + ;
g[!d][j] = g[d][j-] ;
if(f[!d][j] == f[d][j])
g[!d][j] = (g[!d][j] + g[d][j]) % MOD ;
if(f[!d][j] == f[!d][j-])
g[!d][j] = (g[!d][j] + g[!d][j-]) % MOD ;
}
else
{
f[!d][j] = max(f[d][j], f[!d][j-]) ;
if(f[!d][j] == f[d][j])
g[!d][j] = (g[!d][j] + g[d][j]) % MOD ;
if(f[!d][j] == f[!d][j-])
g[!d][j] = (g[!d][j] + g[!d][j-]) % MOD ;
if(f[!d][j] == f[d][j-])
g[!d][j] = ( g[!d][j] - g[d][j-] + MOD) % MOD ;
}
}
d = !d ;
}
return d ;
}
acm-DP整理的更多相关文章
- 背包dp整理
01背包 动态规划是一种高效的算法.在数学和计算机科学中,是一种将复杂问题的分成多个简单的小问题思想 ---- 分而治之.因此我们使用动态规划的时候,原问题必须是重叠的子问题.运用动态规划设计的算法比 ...
- ACM算法整理(不断补充ing)
动态规划 1.背包问题 (1)01背包 ,n) DFR(v,V,C[i]) F[v]=max(F[v],F[v-C[i]]+W[i]); } //初始化时 //若背包不一定装满F全初始化为0 //若装 ...
- codeforces 414B B. Mashmokh and ACM(dp)
题目链接: B. Mashmokh and ACM time limit per test 1 second memory limit per test 256 megabytes input sta ...
- Codeforces Round #240 (Div. 1) B. Mashmokh and ACM DP
B. Mashmokh and ACM ...
- B. Mashmokh and ACM(dp)
http://codeforces.com/problemset/problem/414/B B. Mashmokh and ACM time limit per test 1 second memo ...
- 数位dp整理
数位dp的思想就在于递归,记录当前的某一个唯一状态,依次递归下去,要注意唯一. 数位dp常设的状态有当前位置,上一数字,是否具有前导零,是否有限制. 1.CodeForces 55DBeautiful ...
- DP整理(未完待续)
一.资源问题 T1 机器分配 已知条件:每家公司分配x台机器的盈利 令f[i][j]表示前i公司分配j台机器的最优解 转移:f[i][j]=max(f[i-1][j-k]+w[i][k]) 初始化:f ...
- 【转】斜率优化DP和四边形不等式优化DP整理
(自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...
- 背包DP 整理
题目 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 基本思路 这是最基础的背包问题,特点是: ...
- 数位dp整理 && 例题HDU - 2089 不要62 && 例题 HDU - 3555 Bomb
数位dp: 数位dp是一种计数用的dp,一般就是要统计一个区间[li,ri]内满足一些条件数的个数.所谓数位dp,字面意思就是在数位上进行dp.数位的含义:一个数有个位.十位.百位.千位......数 ...
随机推荐
- Scrum中的User Story
我们通常用User Story来描述Backlog里的各个Backlog项,User Story是从用户的角度对系统的某个功能模块所作的简短描述.一个User Story描述了项目中的一个小功能,以及 ...
- 关于ref与out的区别
写在最前面 这几天一直在公司接受培训,都是一些基础的知识,同时也乘着这个机会巩固一下自己的基础,基础太重要了.前些时一直看的是多线程方面的知识,接下来我会写一些其他方面的知识,毕竟作为一个实习新人得和 ...
- python读写配置文件
#coding:utf-8 import ConfigParser class Conf(): def __init__(self,name): self.name = name self.cp = ...
- 找出程序cpu使用率高的原因
确定是CPU过高 使用top观察是否存在CPU使用率过高现象 找出线程 对CPU使用率过高的进程的所有线程进行排序 ps H -e -o pid,tid,pcpu,cmd --sort=pcpu |g ...
- 深入剖析Classloader(二)--根类加载器,扩展类加载器与系统类加载器
原文地址:http://yhjhappy234.blog.163.com/blog/static/31632832201152555245584/?suggestedreading&wumii ...
- Subset leetcode java
题目: Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset mus ...
- boost库在windows下的编译和使用
因为跨平台的原因,现在要使用到boost库,boost库非常大,现在处于摸索阶段. 首先来说boost库在window下的安装和使用. 一.下载 首先从boost官方主页http://www.boos ...
- Altium designer中级篇-名称决定多边形连接样式
在工作中积累了诸多小技巧,可以让工作变的更简单,就比如这个多边形铺铜,与大部分规则的不同之处在于,通过更改多边形的名称,就能达到控制多边形规则的效果.这样多边形铺铜变的及其灵活,下面将对这个经验做一个 ...
- SOCKS5协议
SOCKS5 是一个代理协议,这种协议对本身所代理的内容并不关心,可用于穿越防火墙. 例如我有一台web服务器,用户可以登陆上去查询公司的关键数据,这样的服务器我肯定是不想放到公网上让别人能随便访问, ...
- 50个非常有用的PHP工具
PHP是使用最为广泛的开源服务器端脚本语言之一,当然PHP并不是速度最快的,但它却是最常用的脚本语言.这里有50个有益的PHP工具,可以大大提高你的编程工作: 调试工具 Webgrind Xdebug ...