动态规划
文章平均质量分 60
lj_acm
这个作者很懒,什么都没留下…
展开
-
poj 1141
这道题让我新认识到的是,做dp题,不一定非得找到具体的某一个最优子结构,可以美剧所有可能子结构的最优解,通过比较得到结果。向此题,只要找到和子结构之间的关系,然后选取最大的,之前一直死去想最有子结构,后来看了黑书。发现lrj所说,只是去找子问题中的最优解。还有就是数据中有空字符串,要注意#include #include #include using namespace std;con原创 2012-11-26 20:03:02 · 443 阅读 · 0 评论 -
hdu 3555
数位DP,各种理解难题#include #include #include #include #define LL long longusing namespace std;unsigned long long n;LL f1[25],f2[25],f3[25];int s[25];int t;int main(){ cin>>t; int i,j,k;原创 2013-04-08 13:54:53 · 842 阅读 · 0 评论 -
sgu 365
数位DP。假设长度为s的数字,如果是题目中要求的数字时,肯定是每个位置i ,j,1--i非递减,j--s非递增,然后枚举每个点把左右两方相乘,但是想了想,这么简单的统计会造成很多重复,然后再分析,对于i,j无非三种情况i所在位置数字a>j所在位置数字b,a==b,a#include #include #define LL long longusing namespace std;LL原创 2013-04-10 14:13:55 · 823 阅读 · 1 评论 -
hdu 4003
树形DP,f[j][i]表示有j个robot遍历i及其子树并且在此子树返回地球所需的最小值,但还有k个robot遍历子树i及其子树,再返回父亲节点m个机器人这种情况,但是可以证明这种情况一定不会是最优解,所以不予考虑。还有一个地方就是f[0][i]表示用0个robot遍历意思就是说用n个机器人遍历此子树,再返回,可知n=1,道理和前面那种情况的道理一样。在求f[i][j]是用的是分组背包的思想,刚原创 2013-04-16 19:56:44 · 732 阅读 · 0 评论 -
poj 1321
状态压缩DP,f[j][i]表示前i行棋子放置状态状态为j的方法数就0#include #include #include using namespace std;int n,k;int num[10],f[1<<8][10],vis[10][10],pa[1<<8];int main(){ while(~scanf("%d%d",&n,&k)) {原创 2013-04-16 14:01:49 · 768 阅读 · 0 评论 -
poj 1322
状态转移方程还是很容易想出的,但是n的限值1000不知道为什么 1 #include 2 #include 3 #include 4 using namespace std; 5 const int maxn=100+10; 6 double f[2][maxn]; 7 int c; 8 int n,m; 9 int main()10 {11原创 2013-08-06 17:34:49 · 836 阅读 · 0 评论 -
poj 1947
DP解之,边界纠结了两个小时,不过还好一次AC,f[i][j]表示已节点已为根的有j个节点所需去掉的边,这个过程可由分组背包的思想来完成,确定最优解每个子树应该有的节点数。最后就是比较i(i为每个节点的编号)为根的保留p个节点的最小值,p为要保留的节点数。 1 #include 2 #include 3 #include 4 using namespace std;原创 2013-08-06 17:34:45 · 794 阅读 · 0 评论 -
poj 3254
状态压缩DP基础题 1 #include 2 #include 3 #include 4 using namespace std; 5 const int maxn=15; 6 const int mod=100000000; 7 int num[maxn],s[200]; 8 int f[maxn][200],amoun[113]; 9 int ma原创 2013-08-06 17:34:47 · 677 阅读 · 0 评论 -
poj 3612
DP+简单优化,状态转移方程容易看出,优化看了http://hi.baidu.com/forverlin1204/blog/item/df9c62dc0fb16bd38d1029d8.html。哎,太粗心了,初始化时忘了得平方,看了1个多小时才发现 1 #include 2 #include 3 #include 4 using namespace std; 5 co原创 2013-08-06 17:34:51 · 1031 阅读 · 0 评论 -
hdu 1423 LICS
看了http://wenku.baidu.com/view/3e78f223aaea998fcc220ea0.html 1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #define LL long long原创 2013-08-06 17:35:05 · 718 阅读 · 0 评论 -
hdu 4512
LICS的应用。还是从最后的结果考虑,肯定是在某个位置的i左边(包括i)递增的序列,右边(包括i)相应的对称的递减的序列,这个序列肯定是,1--i和i--n的逆序的公共递增序列,而1--i和i--n的逆序的公共递增序列肯定是一个符合题意的选择,那么以i为分界点的最优解肯定就是1--i和i--n的逆序的最长公递增序列。然后枚举位置i取以i为分界点的最优解的最大解就可以了。先按这个思路A了,有很多无用原创 2013-08-06 17:35:08 · 748 阅读 · 0 评论 -
poj 2184
最后的结果s无非属于0~100000,枚举每个s相对应的f的最大值f,比较s+f得到最终的最大值。求每个s相对应的f的最大值f用dp来求解,定义ans[]i[j]表示对于前i组数s的和为j的最大的f值,和01背包类似。ans[i][j]=max(ans[i-1][j],ans[i-1][j-s[i]]+f[i]),状态j原本范围为-100000~100000,所以统一加100000,和0~20原创 2013-08-20 14:36:39 · 723 阅读 · 0 评论 -
hdu 1059
多重背包二进制拆分思想#include #include #include #include #include #include #include #include #define LL long long#define myabs(x) ((x)>0?(x):(-(x)))using namespace std;const int inf=0x3f3f3f3f;int原创 2013-08-20 19:43:08 · 783 阅读 · 0 评论 -
ZOJ 3537
这道题,就是先判断是不是凸多边形。先求出凸包,如果所有点都在凸包上,那这些点就围成了凸多边形,反之则不是。然后就是分割凸多边形了,刚开始也想到了先确定一条边所在的三角形,从而确定分割的边。但边没选好,导致后续的状态很凌乱。后来看了相关的资料。先按一个顺序将多边形的n个点编号1--n。求f[1][n]先以边n--1为基准,确定其所在三角形,然后就得到了两个多边形。得到状态转移方程,f[1][n]=m原创 2013-08-10 00:51:33 · 794 阅读 · 0 评论 -
poj 2923
思路看了http://blog.csdn.net/woshi250hua/article/details/7636061不过是用记忆化搜索写的#include #include #include #include #include #include #include #include #define LL long long#define myabs(x) ((x)>0?原创 2013-08-25 16:14:42 · 757 阅读 · 0 评论 -
HDU 3033
如果枚举每组中选出的情况,情况太多,不行。后来又想对、先01背包求出每个组中每个容量至少选一个的最大值,再对整体进行01背包。容量太大,会超时。后来想,直接对整体进行01背包就可以了,就和多重背包的01背包解法类似。但是为了保证最后的结果是没个组的至少选一个,所以状态f[]i[j]k][定义对于前i组,前j个物品,容量为k的每组至少选一个的最大值。可知f[i][j][k]=max(f[i-1]原创 2013-08-26 20:42:47 · 599 阅读 · 0 评论 -
HDU 3535
定义f[i][j][k]为对于前i个组,前j个物品,容量为k,所有的选择都满足相应组的要求的最大值。混合了三种情况。求解每个状态时,根据相应组的要求,分别进行不同的转移。状态转移方程,三种情况分别讨论,比较好想,具体代码。可以滚动数组优化,不想优化了。今晚不想刷题T_T#include #include #include #include #include #include原创 2013-08-28 00:39:58 · 709 阅读 · 0 评论 -
hdu 4734
简单数位DP,f[i][j]表示i位的数字有多少个数权值小于j,i位的数是实际意义的i位数,就是是以1--9开头,不包括0、#include #include #include #include #include #include #include #include #include #include #define eps 1e-8#define LL long l原创 2013-09-17 15:02:02 · 1312 阅读 · 0 评论 -
uva 11825
从最优解的结果考虑,f(s)表示节点集合s最多可分为多少组,如果s中节点及其所连节点的并集是节点的全集的话说明s至少可分为一组,反之,可知f(s)=0,当确定s至少可分一组时,可知其最优解的组成肯定是s的某一子集s0(s0中各节点及其联接的节点的并集为全集且s0只能分成一组否则会造成浪费)+(s-s0),那么f(s)=max{f(s-s0)+1.#include #include us原创 2013-03-20 14:25:10 · 702 阅读 · 0 评论 -
zoj 3399
单调队列优化DP//状态转移方程:f[i][j]=min(f[i-k][j-1]+(s[i]-s[i-p])*g[j])#include #include #include #define LL long longusing namespace std;const LL inf=0x3f3f3f3f3f3f3f3f;LL x[10000+10],s[10000+10],q[100原创 2013-04-06 13:24:00 · 805 阅读 · 0 评论 -
poj 1014
多重背包问题,在网上看了背包九讲的前三篇,但感觉还是理解的不够透彻,过一段时间集中搞一下dp,现在就当预习啦#include #include using namespace std;int f[20001*6],m[7];int main(){ int t=0; while(cin>>m[1]>>m[2]>>m[3]>>m[4]>>m[5]>>m[6]) { t++;原创 2012-11-16 18:55:24 · 413 阅读 · 0 评论 -
poj 1088
气死我啦!!!!!!!!!!!!!,因为第十行的x,y错写成maxn,导致N此TLE,靠,还让我调了两个小时,为什么这么粗心,以后碰到这种情况,先从头到尾的把代码看一遍,看是否犯了什么低级错误dp,记忆化搜索#include using namespace std;const int maxn=101;int map[maxn][maxn];int dis[maxn][maxn];原创 2012-11-18 19:56:42 · 450 阅读 · 0 评论 -
poj 1050
此题数据规模不大,可以通过暴力水过,代码如下#include using namespace std;const int maxn=101;int num[maxn][maxn]; int n;int getM(){ int i,j,k,i2,j2; int f[maxn]; int max=-1<<20,sum; for(i=1;i<=n;i++)原创 2012-11-18 16:43:08 · 502 阅读 · 0 评论 -
poj 1163
最最基础的dp,刚刚开始刷dp题,想了一到自认为很难理解的dp题(网上说是水题,但对于菜鸟我来说,貌似有点难度),想了一下午都没想清楚他的原理,先水这一道题,之后再仔细想想那道“水”题的原理#include using namespace std;const int maxn=101;int tri[maxn][maxn],f[maxn][maxn];int n;int main()原创 2012-11-20 19:27:59 · 422 阅读 · 0 评论 -
poj 1160
dp,详细说明在代码中//在最优解中,一个邮局肯定分管了一部分的村庄,那么通过枚举最后一个邮局所分管的范围,(由于坐标上的n个点,//离这N个点距离之和最短的点一定是这些点的个数的中位数,如果N为偶数,那么这个点一定在包含中位数的区间整个范围内//包括边界点)通过最后一个邮局的分管范围可确定最后一个邮局的位置,并且可得最后一个邮局所分管的村庄到这个邮局的最短距离之和,//就可得到到状原创 2012-11-22 19:28:19 · 602 阅读 · 0 评论 -
poj 1458
dp ,经典LCS,你懂的,不解释//dp 经典的LCS问题。对于s1,s2,如果c(s1)=c(s2),则f(s1,s2)=f(s1-1,s2-1,)+1,如果c(s2)!=c(s1),则//f(s1,s2)=max{f(s1-1,s2),f(s1,s2-1)},边界是f(s1,0)=0,f(0,s2)=0; #include #include #include using nam原创 2012-11-23 17:30:57 · 496 阅读 · 0 评论 -
poj 1159
dp,LCS的应用//求出输入的字符串和他的回文串的LCS的长度l,用此字符串的长度n-l,即得结果//还有存储的问题,如果用f[maxn][maxn]存储的话会超内存,可通过滚动数组优化//因为求当前f[i][j]时可能会用到f[i-1][j-1],f[i-1][j],f[i][j-1],观察发现i,j//只用到当前的i,i-1,二者可用奇偶性区分,只需用一个f[i%2][j]就可表示原创 2012-11-24 10:28:14 · 535 阅读 · 0 评论 -
poj 1187
//读了半大天题终于发现就是LIS问题#include #include using namespace std;const int maxn=100000;const int inf=1<<30;int s[maxn],r[maxn],d[maxn],g[maxn];int n;int low_bound(int x){ int high=n,low=0,mid; whil原创 2012-11-25 11:49:50 · 518 阅读 · 0 评论 -
hdu 1087
dp水题,不解释#include #include using namespace std;const int maxn=1000+10;int v[maxn];long long sumv[maxn];int main(){ int n; while(~scanf("%d",&n)&&n) { int i,j; for(i=1;i<=n;i++) scanf("%原创 2013-02-02 16:28:17 · 357 阅读 · 0 评论 -
uva 1394&poj 3517
递推,把问题转化为具有相同问题的子问题,通过子问题最后所剩余的编号,退出此问题所剩余的编号#include using namespace std;const int maxn=10000+10;int f[maxn];int main(){ int n,k,m; while(~scanf("%d %d %d",&n,&k,&m)) { if(!n&&!k&&!m) bre原创 2013-03-12 19:51:27 · 713 阅读 · 0 评论 -
uva 10891
dp状态转移方程:d(i,j)=sum(i,j)-min{d(i+1,j),d(i+2,j)...d(j,j),d(i,j-1),d(i,j-2)...d(i,i),0}可化为d(i,j)=sum(i,j)-min{f(i+1,j),g(i,j-1),0}#include #include #include using namespace std;const int m原创 2013-03-13 19:36:22 · 816 阅读 · 0 评论 -
poj 1631
又是LIS,又没看出来,写了一个O(n2),用滚动数组优化的算法,超时,瞥了一眼discuss看到了LIS这个字眼,一想,还果然可转化为LIS,而且还这么明显,居然没看出来#include #include #include using namespace std;const int maxn=40000+10;const int inf=200000000;int n原创 2013-03-14 21:26:26 · 661 阅读 · 0 评论 -
poj 1185
状态压缩,看了周伟的动态规划之状态压缩,讲解的很详细,从写程序,到ac花了7个小时,3个小时敲代码,并理思路,4个小时调错,最后发现还是粗心问题,算法上病没有错误,不能在等啦,以后wa后,先仔细把代码看一遍,要有耐心呢,不能过度依赖调试,可能后者会浪费更多的时间#include #include #include #define max(a,b) ((a)>(b)?(a):(b))us原创 2013-03-28 22:03:46 · 735 阅读 · 0 评论 -
poj 3345
树形DP,f(i,j)表示i节点及其子树得到j个国家所需的最小贿赂,对于j==i子树的节点总数sum,所需的最小费用肯定就是i节点本身的cost,对于j//思路来啦#include #include #include #define mem(a,b) memset(a,b,sizeof(a))#define min(a,b) ((a)<(b)?(a):(b))using names原创 2013-03-30 12:36:16 · 749 阅读 · 0 评论 -
poj 2374
dp+线段树,dp是核心,线段树用来优化复杂度,dp过程好像,但是要确定从一个fence边缘向下沿直线走,下一个fence是哪个,最朴素的想法就是从上到下扫描,时间为O(n2),数据量比较大,可能会超时。然后用线段树来优化这个过程,当输入第i个fence的左右点时,1~i-1的fence所覆盖区间已插入到了线段树中(并在所覆盖的区间发记录fence编号)那么此时,求fence(i)的左点l向下会走原创 2013-03-31 13:00:32 · 872 阅读 · 0 评论 -
poj 2355
还是思维不够灵活,刚开始,只想到了那个O(n3)的算法,知道肯定不行,苦苦思索,实在想不出来,浏览了一下其他人的博客,刚扫一眼,突然想到了还是从最优解的最后的状态考虑,得到了O(n2)的算法,就是对于节点i,枚举,在他左边的与他举例小于l3的点,得到状态转移方程f[i]=min(f[j]+cost),ac之,然后看了浩神的博客,还可以用二分优化,想了想,确实可以,因为点到s起点的举例是单调非减的,原创 2013-03-31 18:43:15 · 835 阅读 · 0 评论 -
poj 2063
完全背包问题的变形,79ms,不过此题需要一个优化,就是把背包实际容量除以1000,不优化的话,数据量很大,会超时。刚开始优化直接定义成double,除了之后再乘,wa,因为有浮点误差,后来考虑了一下,改为了int,ac#include #include using namespace std;int amount;int d,year;int intere[11];int v[1原创 2013-03-19 18:54:09 · 665 阅读 · 0 评论 -
poj 2392
对于m的容量的背包,对于n个物品所能得到的最大值,最优解中a值最大的物品,放到背包的他所能放置的最上方,并且有多少放多少到最上面(最优解中a值小于他的还是可以放),可知这样做不会丢失最优解。所以对于前n个物品,先决策a值最大的物品放多少个,并且放置在他所能放置的最上方,再决策于剩下的容量和剩下的物品的最优解。所以先对物品按a值排序,即f[i[j]=max(f[i-1][j-k*h[i]]+h[i]原创 2013-09-17 23:54:42 · 899 阅读 · 0 评论