[考试]20151016动态规划
1、前言
互测题第五弹——来自z123z123d的动态规划,我已经走好了丧病的准备,所以大暴力伺候。结果!我发现了更丧病的地方——卡空间!整整100分。再见。其他题的话,,,基本上不可做,有的不敢写,有的根本写不出。
2、Matrix 矩阵
大概题意:有一个n*m的矩阵,从左上角走到右下角,只能向下或向右走。每个点上有一个重量为v[i][j],价值为w[i][j]的物品,你有一个容量为S的背包,经过一个点你可以选择将它放入背包,求得到的最大价值。
题解:
给0-1背包强行加了个矩阵,想法还是不错的。转移方式由以前的一层一层转移变为按坐标转移,但是!有一个很重要的事情要考虑!n,m,S<=400,直接开一个三维数组会爆空间,244MB左右,然后我光荣牺牲了。所以要用滚动数组。
3、Product 产品排序
大概题意:你是一个公司的员工,会按时间顺序受到些产品订单需要你是一个公司的员工,会按时间顺序受到些产品订单需要用一个栈来改变这些订单的顺序(每个产品都必须入栈和出栈一次 )。按初始顺序,每次可以将一个产品 入栈或顶弹至现在的列末尾。每个产品有一个制作时间ti和单位时间惩罚值di,请最小化总惩罚值,指每个产品完成时间×惩罚值的总和。
题解:
考虑最后出栈的是i,则1到i-1在i入栈前就已经弹出,而与i+1到n的顺序没有关系,并且i+1到n的总惩罚值只和他们内部的顺序与1到i的总时间相关,故两方面之间是可以看做两个不受关联的子问题的,即[1,i-1]和[i+1,n]。
则令f[i][j]表示[l,r]的最小惩罚值。f[i][j] = min(f[l][mid - 1]+f[mid + 1][r] + (st[mid - 1] - st[l - 1]) * (sd[r] - sd[mid]) + (st[r] - st[l - 1]) * d[mid])(l <= mid <= r),其中st为时间前缀和,sd为惩罚前缀和。
4、Wave 波浪数
大概题意:求长度为n的排列个数,满足每两个元素之间的差值绝对值的总和为m。
题解:
首先要知道在动态规划中一种常见的排列的生成方式,每次加入一个数然后和前面的数交换或者插入一个位置,再计算权值。因为是绝对值,所以考虑从小到大添加,但是发现在交换过程中,与前面序列的状态有关,不好转移,但是n很小,故添加一个状态以转移。
在加入一个元素之后我们决策其相邻的两个元素与其的大小关系,此时就加上它对答案的影响,这样一来我们相当于将当前序列割成几段,后面的数只能插入段与段的间隙之中。考虑到两端间隙的特殊性,令f[i][j][k][s]表示考虑完前i个数,有j个间隔,两端间隔为k个,波动值为k的情况的方案数。
5、Inversion 逆序对
大概题意:有一个1-n的排列,你会依次进行m次操作,第i次操作表示为(xi,yi),交换以这两个数的值为下标的元素,每次操作有一半的几率成功。你需要求最后序列的逆序对的期望个数。
题解:
动态规划的题目套上一个数学期望的样式。因为逆序对是(x,y)的形式,考虑每一对(i,j)对答案的贡献。f[i][j]表示a[i]>a[j]的概率,发现每一操作只影响O(n)个f值,于是可以处理出每个f的初始值,每次更新受影响的值即可。