??xml version="1.0" encoding="utf-8" standalone="yes"?>
2009q??9?星期?br>dp: re[i][j]=max{四个方向所得的最大?的最大值}
#include<iostream>
using namespace std;
#define MAX 102
int m[MAX][MAX],re[MAX][MAX];
int d[4][2]=
{
{0,1},
{0,-1},
{1,0},
{-1,0}};
int r,c;
int dfs(int i,int j)
{
if(re[i][j])return re[i][j];
int maxv=0,tmp;
for(int k=0;k<4;++k)
{
int x=i+d[k][0];
int y=j+d[k][1];
if(x>-1&&x<r&&y>-1&&y<c)
{
if(m[i][j]>m[x][y])
{
tmp=dfs(x,y)+1;
if(tmp>maxv)maxv=tmp;
}
}
}
return maxv;
}
int main()
{
int ans=0,tmp;
scanf("%d%d",&r,&c);
for(int i=0;i<r;++i)
for(int j=0;j<c;++j)
{
scanf("%d",&m[i][j]);
re[i][j]=0;
}
for(int i=0;i<r;++i)
for(int j=0;j<c;++j)
{
re[i][j]=dfs(i,j);
if(ans<re[i][j])ans=re[i][j];
}
printf("%d\n",ans+1);
// system("pause");
return 0;
}
]]>背包问题Q?/span>01Q完全,多重Q未试Q?br>
#define MAXN 120005 //maxcash
#define MAX 11
int n[MAX],c[MAX];//n[i]物品i的数量,c[i]费用Qw[i]价?nbsp;
int f[MAXN];//MAXN为最大容?nbsp;Q存储状态?nbsp;
int V,N;//V最大容量,N物品个数
/**//*01背包物品 */
void ZeroOnePack(int cost,int weight)
{
//一?1背包物品
// 费用costQ?nbsp;价值weightQ?1背包
for(int v=V;v>=cost;--v)
f[v]=max(f[v],f[v-cost]+weight);
return;
}
void ZeroOnePackMain()
{
/**//*N件物?nbsp;定w为V的背包,Wi件物品费用c[i]Qh值w[i],求{入背包可以获取的最大h?nbsp;
原方Ef[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]}
化方E:f[v]=max{f[v],f[v-cost]+weight};
*/
for(int i=0;i<N;i++)
ZeroOnePack(cost[i],weight[i]);
return;
}
/**//*一件完全背?/span>*/
void CompletePack(int costQ?/span>int weight)
{
//一件物品完全背?nbsp;
//N U物?nbsp;定w V,c[i],w[i], 每一U无?求最大h?nbsp;
// 费用costQ?nbsp;价值weightQ完全背?nbsp;
//对多U物品的问题Q可以添加的优化Qa.L大于V的物?b.c[i]<=c[j] and w[i]>=w[j]L物品j
for(int v=cost;v<=V;++v)
f[v]=max(f[v],f[v-cost]+weight);
return;
}
/**//*一件多重背?/span>*/
void MultiplePack(int cost,int weight,int amount)
{
//多重背包
//1U物?nbsp;费用costQ?nbsp;价值weightQ个数amount
//二进制优化log(amount)
if(c*amount>=V)
{
CompletePack(cost,weight);
return;
}
int k=1;
while(k<amount)
{
ZeroOnePack(k*cost);
amount-=k;
k*=2;
}
ZeroOnePack(amount*cost);
return;
}
]]>
第iU面额分成若q面额的billQ这些bill面额?pL1Q?Q?Q。。。?^(k-1),n[i]-2^k+1 分别乘以d[i] Q?nbsp;q且n[i]-2^k+1>0;
(我也是看别h的,找个数试一下就知道了,用这些面额系数就可以Q就可以l成<=n[i]的所有可?
O(V* S log n[i])
f[v]表示定wv所能得到的L
化方E? f[v]=max{f[v],f[v-c]+c}
f[]初始都ؓ0
多重背包 详见背包九讲
#include<iostream>
using namespace std;
#define MAXN 120005 //maxcash
#define MAX 11
int n[MAX],d[MAX];
int f[MAXN];
int V,N;
void ZeroOnePack(int c){
for(int v=V;v>=c;--v){
f[v]=max(f[v],f[v-c]+c);
}
return;
}
void CompletePack(int c){
for(int v=c;v<=V;++v){
f[v]=max(f[v],f[v-c]+c);
}
return;
}
void MultiplePack(int c,int amount){
if(c*amount>=V){
CompletePack(c);
return;
}
int k=1;
while(k<amount){
ZeroOnePack(k*c);
amount-=k;
k*=2;
}
ZeroOnePack(amount*c);
return;
}
int main()
{
int a,b;
while(scanf("%d%d",&V,&N)!=EOF){
if(!V&&!N)continue;
int flag=0;
for(int i=0;i<=V;++i)f[i]=0;
// memset(f,0,sizeof(f));
for(int i=0;i<N;++i){
scanf("%d%d",&a,&b);
n[i]=a,d[i]=b;
if(d[i]==V){f[V]=V;flag=1;}
}
if(V==0)f[V]=0,flag=1;
if(!flag){
for(int i=0;i<N;++i)
if(n[i]&&d[i]<=V)
MultiplePack(d[i],n[i]);
}
printf("%d\n",f[V]);
}
return 0;
}
]]>
型如下表的简单DP(可参考lrj的书 page149):
E[j]=opt{D+w(i,j)} (poj3267,poj1836,poj1260,poj2533)
E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij} (最长公共子序列)
(poj3176,poj1080,poj1159)
C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最优二分检索树问题)
较ؓ复杂的动态规?如动态规划解特别的施行商问题{?
(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)
记录状态的动态规? (POJ3254,poj2411,poj1185)
树型动态规?poj2057,poj1947,poj2486,poj3140)
背包九讲 http://www.concretevitamin.com.cn/informatics/Pack/Index.html
]]>#include<iostream>
using namespace std;
#define MAX 10000
#define base 5000
#define hmax 21
int m[hmax][MAX];
int h[hmax],w[hmax];
int c,g;
/**//*
m[i,j]表示前i个位|?nbsp;得到力矩为j的方案的 数目
m[i][j]=Σm[i-1,j-w[i]*h[k]] i砝码?nbsp; k位置
base避免负数
*/
int main()
{
while(scanf("%d%d",&c,&g)!=EOF){
for(int i=0;i<c;++i)scanf("%d",&h[i]);
for(int i=0;i<g;++i)scanf("%d",&w[i]);
memset(m,0,sizeof(m));
for(int i=0;i<c;++i)++m[0][w[0]*h[i]+base];
for(int i=1;i<g;++i)
for( int j=-base;j<=base;++j){
int tmp=0;
for( int k=0;k<c;++k)
if( m[i-1][base+j-h[k]*w[i]])tmp+=m[i-1][base+j-h[k]*w[i]];
m[i][base+j]=tmp;
}
printf("%d\n",m[g-1][base]);
}
return 0;
}
l箋q稚C留代码,q脓出出来?
]]>
by Amber
写在前面Q?/span>
从状态类型分Qƈ不表CZ题只从属于一cR其实一cd是一U状态的表示Ҏ。可以好几种Ҏl合成一个状态,来解决问题?/span>
共性ȝ
本类的状态是基础的基Q大部分的动态规划都要用到它Q成Z个维?/span>
一般来_有两U编L状态:
状?/span>(i)表示?/span>i个元素决{组成的一个状态?/span>
状?/span>(i)表示用到了第i个元素,和其他在1?/span>i-1间的元素Q决{组成有的一个状态?/span>
题库
a) 最长不下降子序?/span>
以一元组(i)作ؓ状态,表示W?/span>i个作为序列的最后一个点的时候的最长序列。于是很Ҏ惛_O(n2)得算法。但本题?font color=red>合理l织状?/span>Q引入一个单调的辅助数组Q利用单调性二分查找,优化?/span>O(nlogn)。关于优化详见优化章?/span>
一些问题可数?font color=red>有序?/span>Q{化成本题?/span>
应用Q?/span>
拦截导弹(NOIP99 Advance 1) 是原题?/span>
Beautiful People (sgu199)Q要数据有序化Q其中一个权作ؓW一关键字不下降排列Q另一个权作ؓW二关键字不上升?/span>
Segment (ural 1078)Q将U段的左端点有序化就可以了?/span>
b) LCS
状?/span>(i,j)Q表C第1个字W串的第i位,与第2个字W串的第j位匹配,得到的最长的丌Ӏ若有多个串?/span>LCSQ则加维Q即几个串就几个l。我也将此题归入路径问题?/span>
c) 花店q布置(IOI99)
?strong>路径问题?/span>
共性ȝ
本类问题与下一章的划分问题?strong>决策的分割点无序交集比较大(占本c问题的30%Q?/span>
题库
a) 矛_合ƈ
?strong>划分问题
b) 模版匚w(CEOI01,Patten)
q题Ҏ的地Ҏ状态的值是一个集合而不是一个数?/span>
c) 不可分解的编?/span>(ACM World Final 2002)
d) Electric Path(ural1143)
e) 邮局(IOI2000 Day2 1)
若状态表C的思\从第i个村庄可以从属于哪个邮局Q无最优子l构。{变一个方向:W?/span>k个邮局可以“控制”一个区间的村庄[i,j]。于是方E就昄?/span>:
f(k,i,j)=min{f(k-1,p,i-1)+w(i,j)}(k-1<=p<=i-1)
S(i) 为村?/span>i到原点的距离?/span>
w(i,j)=min{k| Sum{|S(k)-S(p)|}(i<=p<=j)}(i<=k<=j) 扑ֈ[i,j]间最好的一个邮局炏V?/span>
不过可以发现Sum{|S(k)-S(p)|是单调的Q所以取中位数就可以了。即上式?/span>k的取D围只?/span>floor((i+j)/2), ceil((i+j)/2)两个?/span>Floor是下取整?/span>Ceil是上取整。这hơ{UL间降?/span>O(1)?/span>
注意到是区间q箋的,?/span>(p,i-1) ?/span>(i, j) 中的 i-1, i是连l的Q所以空间可以降l_f(i,j)表示攑։i个邮局到前j个村庄的最优倹{?/span>
f(i,j)=min{f(i-1,p-1)+w(p,j)}(i-1<=p<=j-1}
e(i,j) 为当f(i,j)到达最优值时?/span>p.
通过证明四边形不{式Q得?/span>e(i,j)<=e(i,j+1)<=e(i+1,j+1)
决策数量又少了一个数量?/span>
共性ȝ
之后的一些问题,状态是由坐标维与其他的l组成。本cM划分问题(?/span>2l或多维的坐标系的划?/span>)?strong>路径问题的交集占本类问题中大多数?/span>
题库
a) 盘分割(NOI99 4)
主要是将公式变ŞQ变形后的公式很Ҏ看出方程?/span>
状态是?/span>2个坐标组成的4元组(x1,y1)(x2,y2)Q表CZ个子盘。这有点像之前的区间动态规划,只不q是?/span>1l{2l?/span>
后见路径问题?/span>
共性ȝ
题库
a) 01背包
应用Q?/span>
装箱问题Q?/span>NOIP01 Trade 4Q?/span>
是原题?/span>
值币分割
可利用方E的性质Q空间降1l?/span>
币值可重复的值币分割(pku1742, Problem F LouTianCheng’s Contest in POJ)
使用左右法在定位上加速?/span>
另给状态加一个属?/span>last,记录上一ơ剩下的可用的同币值硬币数Q利用了当前转移是唯一前驱的特点)?/span>
b) 取火柴问?/span>(sgu153 Playing with matches)
c) Stone Pile(ural1005 Stone Pile)
d) 公\巡?/span>(CTSC2000)
共性ȝ
1Q?font face="Times New Roman" size=1> 动态规划的序
一般按照后序遍历的序Q即处理完儿子再处理当前节点Q才W合树的子结构的性质?/span>
2Q?font face="Times New Roman" size=1> 多叉树{换ؓ二叉?/span>
׃要分配附加维到各个节点,而分配附加维是个划分问题Q若q是按当前节点到各个儿子节点分配Q则成了一?strong>整数划分问题,O(n2)。所以要把多叉树转换Z叉树Q这h能按动态规划的方式只决{当前点的分配问?/span>, O(n)?/span>
3Q?font face="Times New Roman" size=1> 加当前点的选或不选的常数l?/span>
加此l解决的是后效性问题?/span>
……………………
4Q?font face="Times New Roman" size=1> 在将边信息{成树时的技?/span>
读入的边分裂成2条边Q将q?/span>2条边兌hQ就是找C条边Q另一条边的编号就知道Q。用前向星表C法表示边(按vҎ序)Q以后用边的时候,用了一条边打不可用标志Q也关联边打不可用标志。这样可以保?/span>O(n)的时间完成信息处理,而且在父节点扑ք子的q程中带来很大的方便?/span>
5Q?font face="Times New Roman" size=1> 复杂?/span>
树型动态规划复杂度基本上是O(n)Q若有附加维mQ则?/span>O(nm)?/span>
题库
a) 选课(CTSC97-3)
׃要分配课E数Q所以要多叉树{换ؓ二叉树?/span>
b) 贪吃的九头龙(NOI02-3)
若小头数大于1的话Q则让不同的头吃一D|枝的2个端炏V?/span>
q样把问题转化成:附加l是大头吃的个数Q当前点׃由大头吃的常数维的动态规划。由于涉及划分问题,所以要多叉树{换ؓ二叉树?/span>
c) 求树的质?/span>(sgu134 Centroid)
l出一边不带权的树,求点,使得L此点?/span>,剩下的最大的q通子囄点数最?/span>.
d) 求树中的Ҏq距Lq?/span>
l出一边带权的树Q求树中的点Q得此点到树中的其他结点的最q距Lq?/span>
Computer Network (sgu149)
Computer Net (ural1056)
共性ȝ
1) 数据Ҏ?/span>
l出的数据在某一个或几个l度上一般具有比较小的范_可以枚D一cȝ状态)?/span>
一个枚丄状态是一个集合?/span>
2) ~码
׃集合中元素个数的不定性或范围大,直接开数组存,不好索引数组Q编E复杂度太高Q,所以要集合编码?/span>
利用数据的可枚D性,枚丄状?/span>(集合)~码。一般来说码值的范围要很(量排除无用的码|如炮兵:当前格和上格存在炮兵的情冉|非法的,可以排除Q?/span>
规定~码的码g表的意思,要尽量规定好l护的码倹{(如炮兵:当前格存在炮늚?/span>2Q上格存在炮는1。这样下一层的规划Ӟ只要码?/span>-1卛_Q?/span>
有时候可以直接利用编码的序动态规划,因ؓq时~码已经?font color=red>拓补有序。如TSP问题当前已选点集合的状态的前驱的编码的g定比当前的编码的值小?/span>
3) 状态压~?/span>
Ҏ限阶D늚攄情况Q行走情늼码(其实质也是放|的集合或行走\U的集合Q,q样的编码,也有之:“状态压~?#8221;。此c题?#8220;炮兵阵地”为典型,q行扩展?/span>
题库
a) 购物Q?/span>IOI95-2Q?/span>
可将每种物品?/span>5q制~码。(5为每U物品数的上限)
׃物品数的上限?/span>5Q比较小Q也可直接开数组存?/span>
b) Roger游戏d一Q?/span>CTSC98 Day2 4Q?/span>
一个正方体在一个方格内的状态只?/span>24U,而且可以通过剙和前面来表示Q这L3l的状?/span>(x,y,p)可以解冻Ip?/span>1?/span>24U状态中的一U?/span>
c) TSP问题
观察一?/span>TSP的搜索过E: for (x in 未选点) TSP(x)
卛_前\的最后一个节点ؓx,现在要选择下一个节?/span>y,?/span>y要在未选点的集合中。若未选点或已选点的集合已定Q则后效性消除。可?/span>DP。状态ؓ?/span>X为当前\的已选点的集?/span>(?/span>i)Q当前\的最后一个节点ؓi?/span>2元组(X,i)为经q已选点的集?/span>X到节?/span>i的最短长度。将X~码卛_?/span>
注意Q?font color=red>q没有因为动态规划将问题?/span>NPcd?/span>Pc?/span>?/span>
应用: DNA Laboratory(Problem B,TU-Darmstadt Programming Contest 2004)
每个串的交q部分求出,可以将问题专成TSP
但要输出字典序最的Q则需要注?/span>DP序?/span>
有具体的报告?/span>
d) 炮兵阵地
十分l典Q详?font color=red>报告?/span>
应用:
Another Chocolate Maniac(sgu132) cM炮兵的做法的最|只不q是求最|ȝ炏V?/span>
Hardwood floor(sgu131) cM炮兵的做法的l计
Little Knights(sgu225) cM炮兵的做法的l计,数据量太大要const
Little Kings(sgu223) cM炮兵的做法的l计
Bugs公司(CEOI 2002) cM炮兵的做法的最?/span>
共性ȝ
要利用上ơ的一些运?#8220;剩下”的@环变量作当前循环的边界,主要在于扑և一U决{顺序,使之成立?/span>
题库
a) 奶牛场
b) Communication System
数据有序化, 从大到小枚D带宽, 每次可利用上ơ处理的l果Min, 来决{当前状态。称作P?/span>, 或就是一U动态规划?/span>
(zju1409, Problem C Tehran 2002 Iran Nationwide Internet Programming Contest)
题库
a) Magic Trick (Problem G, TU-Darmstadt Programming Contest 2004)
递推
1)01l计(CTSC99 1)
2)卡特兰数
circle(sgu130)
3)鹰蛋
共性ȝ
a) ?span>序?/span>
每次决策的点的编h有序的,卌按决{的序输出分割点的~号的话Q编h有序的,满分割点的~号按升序排列?/span>
b) 方程一般Ş?/span>
f(n,m)=optimize{f(k,m-1)+w(k+1,n)}
(n,m)表示?/span>1?/span>n个点中划分ؓm个部分的最优|k为决{的分割点,即第m个部分ؓk+1?/span>nQ这?/span>optimize可以?/span>max,min?/span>
题库
a) 整数划分
常应用在一个权分配l一定的分割块Q如Q将大堆的石子分成一定的堆Q小堆可为空Q大堆要分完。有时应用在树型动态规划(二叉转多叉)中?/span>
b) 乘积最?/span>(NOIP00 Advance 2)
是按上面的一般式的方E做?/span>
共性ȝ
a) 无序?/span>
每次决策的点的编h无序的,卌按决{的递归序输出分割点的~号的话Q编h无序的?/span>
b) 方程一般Ş?/span>
f(i,j)=optimize{f(i,k-1)+f(k+1,j)}+w(i,j)
(i,j)表示?/span>i?/span>j的范围内选取一个分割点k的最优|子问题是分割点左?/span>(i,k-1)和右?/span>(k+1,j)的点的范围的最优|q里optimize可以?/span>max,min?/span>
方程很类?/span>2叉树的性质?/span>
c) 四边形不{式
此类的问题,有些可用四边形不{式优化。见优化章?/span>
题库
a) 矛_合ƈ(NOI95 2)
l典Q详见报告?/span>
可用四边形不{式优化?/span>O(n2)
其实q可以用cM堆的数据l构?/span>O(nlogn)的时间内完成Q但q就不是动态规划了?/span>
应用Q?/span>
构造最优二叉排序树(CTSC96 2)
b) 多边?/span>(IOI98)
q题值的正负号处理要注意Q乘法运,׃W号的加入,使原本的正的最优解Q一下变成负的?/span>
c) 加分二叉?/span>(NOIP03 Advance 3)
方程是一般式Q{Uȝ函数Q?/span>w(i,j)=sum(i,k-1)*sum(k+1,j)+d(k)。由?/span>w(i,j)不满_单调性,所以不能用四边形不{式优化?/span>
d) 括号序列(Problem B, NEERC 2001)
q题的分割点不是一个元素,而是元素间的一条线?/span>
主要的思维方式是从递归定义?/span>
共性ȝ
a) 行走方向军_阶段?/span>
有规定源点与l点。每ơ行走方向都有一定的规定Q原点到终点的所有\径Ş成无环有向图?/span>
b) 多源或多?/span>
当多源或多汇Ӟ应该加维Q得每个源Q都有一个\径的状态与之对应。如?/span>n个源的网格类问题Q常常{态是(x1,y1)(x2,y2)…(xn,yn)。但是源太多的话Q空间上不允许,可以降问题{成网l流问题?/span>
c) 双向动态规?/span>
׃有规定源点与l点Q可以双向动态规划,但要考虑效果好不好,理论上是比原来少1/2Q但有时׃可用于决{的状态较,效果׃错了?/span>
d) 决策E疏?/span>
是所谓走法,若对于一个状态,它的前驱或者后l数很少(从无环有向图角度Q就是入度或出度?/span>)Q称决策E疏?/span>
e) 状态稀疏?/span>
是很多状态是没有用的Q如排列?/span>LCS,状态ؓ2l的(x,y)Q但对于一?/span>x只有一?/span>y是有效个。所以实质上状态数q是UŞ的?/span>
本类一些技巧性的东西较多Q在题库中具体说明?/span>
题库
a) Ҏ取数(NOIP00 advance 4)
(x1,y1)(x2,y2)
对角U空间优?/span>
b) 花店q布置(IOI99)
我对本题有个改造:若花瓶无序,如何做,有序指:对于花束i<花束j, 花束i对应的花瓶编?/span><花束j对应的花瓶编受那么这样就是一?/span>NP问题了,可用后面的基于状态压~的动态规划解冟?/span>
最主要的未ȝQ给出相关的题与已有的报告(自己或他人的Q?/span>