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.数位的含义:一个数有个位.十位.百位.千位......数 ...
随机推荐
- python参考手册--第8章
1.模块和import (1)首次import module会做以下3件事: a)创建新的命名空间,用作在该源文件中定义的所有对象的容器.在模块中定义的函数和方法在使用global语句时将访问该命名空 ...
- POJ2031Building a Space Station
http://poj.org/problem?id=2031 题意:你是空间站的一员,太空里有很多球形且体积不一的“小房间”,房间可能相距不近,也可能是接触或者甚至是重叠关系,所有的房间都必须相连,这 ...
- maven3常用命令\创建Project
转自 http://blog.csdn.net/edward0830ly/article/details/8748986 ------------------------------maven3常用命 ...
- iOS开发的小技巧(断点打印)
iOS开发中我们会碰到这样的需求:打印沙盒目录,打印对象信息,对象信息可以通过断点查看,有时候对象属性繁多时看起来又比较麻烦. 今天学到一个比较实用的方法: 在运行时打一个断点,当程序停在这个断点后, ...
- java中dao层和service层的区别是什么?
首先解释面上意思,service是业务层,dao是数据访问层.呵呵,这个问题我曾经也有过,记得以前刚学编程的时候,都是在service里直接调用dao,service里面就new一个dao类对象,调用 ...
- 跨域使用jsonp 获取天气预报
<html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> ...
- 散列表 (Hash table,也叫哈希表)
散列表是根据关键字(Key value)而直接访问在内存存储位置的数据结构.也就是说,它通过把键值通过一个函数的计算,映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录 ...
- Android 常用UI控件之TabHost(5)Tab栏在底部且在最上层也不盖tab页
tab栏在底部 <TabHost android:id="@android:id/tabhost" android:layout_width="match_pare ...
- poj 3007 Organize Your Train part II(二叉排序树)
题目:http://poj.org/problem?id=3007 题意:按照图示的改变字符串,问有多少种..字符串.. 思路:分几种排序的方法,,刚开始用map 超时(map效率不高啊..),后来搜 ...
- 扫描.net dll引用dll
最近升级系统里的NHibernate,从3.3到4,项目工程太多, 一个模块分bll,dal,model,web,test,10几个模块,就要60多dll,升级一次太头疼. 编译过后,有时候会有的dl ...