摘要:
[转]动态规划入门练习题一月 5, 2010by玉 逍遥HDU 动态规划(46道题目)倾情奉献~ 【只提供思路与状态转移方程】Robberieshttp://acm.hdu.edu.cn/showproblem.php?pid=2955背 包;第一次做的时候把概率当做背包(放大100000倍化为整数):在此范围内最多能抢多少钱 最脑残的是把总的概率以为是抢N家银行的概率之和… 把状态转移方程写成了f[j]=max{f[j],f[j-q[i].v]+q[i].money}(f[j]表示在概率j之下能抢的大洋);正确的方程是:f[j]=max(f[j],f[j-q[i].money]*q[i].v 阅读全文
摘要:
树状数组树状数组是对一个数组改变某个元素和求和比较实用的数据结构。两中操作都是O(logn)。在解题过程中,我们有时需要维护一个数组的前缀和S[i]=A[1]+A[2]+...+A[i]。 但是不难发现,如果我们修改了任意一个A[i],S[i]、S[i+1]...S[n]都会发生变化。 可以说,每次修改A[i]后,调整前缀和S[]在最坏情况下会需要O(n)的时间。 当n非常大时,程序会运行得非常缓慢。 因此,这里我们引入“树状数组”,它的修改与求和都是O(logn)的,效率非常高。【理论】 为了对树状数组有个形 象的认识,我们先看下面这张图。 如图所示,红色矩形表示的数组C[]就是树状数组.. 阅读全文
摘要:
这题是最长公共子序列的变形,要注意的就是,题目要求输出最长上升子序列的字典排序最小值,最麻烦的就是这个,想了半天都没什么思路,我对最长上升子序列的理解不是很透彻。在网上看了别人的题解,都是用一个结构题来保存状态 (公共子序列的长度,公共子序列的串)我才恍然大悟,既然这样,那不是搜索一遍所有的状态的字符串就可以了吗。#include
#include
#include
#include
#include
using namespace std;
#define MAXN 1010
struct Node
{ int l; string s;
}no[MAXN][MAXN];
char sm[.. 阅读全文
摘要:
此题的大意是给定一个序列,求一个最长的奇数子序列,使得前k个序列上升,后k个序列下降。此题的解法是从左往右求一次最长上升子序列,然后从右往左再求一次最长上升子序列,分别记录在状态变量d1[i],d2[i],求min(d1[i],d2[i])的最大值即可,答案就是2*min-1。#include
#include
#include
#include
#include
using namespace std;
#define MAXN 10010
#define INF 1000000000
int seq[MAXN];
int d1[MAXN],d2[MAXN];
int g[MAXN];
in 阅读全文
摘要:
这个题目的大意就是,给你一个字符串,然后让你求出最少的回文数。我开始傻逼了,写了一个o(n^3)的算法,结果老超时。然后略看了别人的题解,才知道有个如此的转移方程。f[i+1]=min(f[j]+1,其中j~i是回文),基础的动态规划题目,还得多多加强训练。#include
#include
#include
using namespace std;
#define MAXN 1010
#define INF 1000000000
char s[MAXN];
int f[MAXN];
bool isp(int l,int r)
{ bool ok=1; for(int k=... 阅读全文
摘要:
题目的意思是有n台服务器运行着n类程序,一个黑客有n中类的病毒,最多每台服务器可以放一种病毒,但是相邻的服务器会感染同种病毒,只暂停一种服务,问能够暂停的程序的最大种数。解决的方法是,用位表示集合,问题的答案相当于是求出最多集合的组合,组合内的集合并集是全集。求这些组合最大的数目。转移方程式f[s]={f[s^s0],s0这种组合内的集合并集是全集}+1.这里涉及到一些集合的操作:或运算,将元素加入到集合之中。枚举集合的所有组合的可能性:for(int i=0;i0;i=(i-1)&s)
{ //insert code
}代码:#include
#include
#include
us 阅读全文
摘要:
题目的大意是有一个整数组成的序列,两个人轮流取数,只能从一端取一个或者多个数(这里大白书上写错了),当所有的数都被取完的时候,取到的所有的数之和为该玩家的分数,求A的分数-B的分数,两个人都是以最优的方案取值。这个问题使用动态规划求解,子问题就是i~j的子序列先手取得的分数最大值。设d[i][j]表示子序列i~j的先手取数所获得的最大分数则d[i][j]=sum[i][j]-min(d[i+1][j],d[i+2][j],d[i+3][j],...,d[j][j],....,d[i][j-1],d[i][j-2],d[i][j-3],...,d[i][i],0)。0表示所有的数都被先手取完。因 阅读全文
摘要:
题目大意是求两个数列的最长公共子序,由于数列的长度可以达到250*250=62500所以在n^2的时间限内是不可能做到了,这需要一个nlogn的方法。由于每个数字都不相同,因此可以将其转化成求最长上升子序的问题。先记录下第一个序列的下标,然后再检查第二个序列,如果在第一个序列中已经被记录,则该元素是公共元素,但不一定是公共自序中的元素,将他放入一个数组当中,这个数组当中元素的顺序是依照第二个序列的,如果能够找到最长公共子序的话,就必须使得该序列同时遵循第一个和第二个的出现顺序,也就是说,只要是最长上升子序,就是这两个序列的最长公共子序。因此可以转化为求最长上升子序的问题。#include
#i 阅读全文
摘要:
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=31134#problem/B问题的大意是有n个数编号依次为1~n构成一个圈,第一次去掉编号为m的数字,以后没数到k把该数字去掉,问最后剩下什么数字。此题的解法是动态规划,递推。标准的约瑟夫问题是0~n-1的n个数从零开始,每数到k就把该数字去掉,随后剩下什么数字。我们可以将该题化为标准的约瑟夫问题。假设有n个数字的标准约瑟夫问题,编号为0~n-1,第一次去掉的数字是(k-1)%n,则剩下的数字是 k%n, k%n+1 n%k+2,...,n-1,,,,k%n-2我们作如下转换 设 k% 阅读全文
摘要:
这题刘汝佳大白书上的例题,自己总结一番,寻找递推关系。题意是从1~n中选择3个数,一共可以组成多少个三角形。1.组成三角形的条件是x+y>z,假设三角形最大的边是x则有x-y#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;const double eps(1e-8);typedef long long lint;#define clr(x) memset( x , 0 , sizeof(x) )#define repf(i 阅读全文