ACM刷题

由于是直接从txt文本中直接copy过来的,故没有使用latex编写公式
参考《挑战程序设计》

ACM problem list

✗:还未完成
✓:已完成
☆:有部分思路
★:完全没思路

Dynamic Program
基础题

POJ 3176: Cow Bowling ✓
dp[i][j]为坐标(i,j)的最长路径
dp[i][j]=max{dp[i-1][j],dp[i-1][j-1]}+a[i][j]

POJ 2229: Sumsets ✓ ★
法1
完全背包思路
考虑有20个物品,重量分别是2^0,2^1,2^2,...,2^19,求n有多少种塞满方式
dp[i][j]=dp[i-1][j-(1<<(i-1))]+dp[i-1][j]
然而不知道为何这个超时了,这个数据范围肯定不是1e6的
法2
考虑直接递推(好像也可以直接打标找规律)
对i分奇偶讨论
奇数方案是由上一个偶数数字方案中都加1,即dp[i]=dp[i-1]
偶数方案是由上一个奇数数字方案中都加1,和i/2的方案中数字都乘2得到,即dp[i]=dp[i-1]+dp[i>>1]

POJ 2385: Apple Catching ✓
由于有时间,位置,步数,苹果总数目四个变量,于是我先考虑用三维数组
dp[i][j][k]代表时间i时,位置在j棵树下,剩余k步所获得的最大苹果数目
初始化全部为-1,只有dp[0][0][w]=0,因为初始时实在0号树下
dp[i][j][k]=dp[i-1][j][k]
记t为i时刻下落苹果的树,只用考虑树t,因为只有它才会对答案产生贡献
if (dp[i-1][t][k]!=-1) dp[i][t][k]=dp[i-1][t][k]+1
if (dp[i-1][t^1][k+1]!=-1) dp[i][t][k]=dp[i-1][t^1][k+1]+1;
两者取MAX即可得到dp[i][j][k]的值
发现第一维数组可以直接省去,第三维数组从w...1的方向遍历即可,于是只需要dp[j][k],时间复杂度O(T*W)

POJ 3616: Milking Time ✓
每个区间左端点记l[i],右端点记r[i],价值记e[i],r为休息时间
dp[i]为区间1...i能产生的最大价值,并以区间i结尾
先对右端点从小到大排序
dp[i]=max{e[i],dp[j]:j<=i && r[j]+r<=l[i]}

POJ 3280: Cheapest Palindrome ✓
记添加字符c花费为a[c],删除字符c花费为b[c],dp[i][j]表示将s[i...j]变为回文串的最小花费
if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1]如果所有两段字符相同
dp[i][j]=min{dp[i][j],dp[i+1][j]+min(a[s[i]],b[s[i]])}考虑删除s[i]或者在j+1处添加s[i],都只用再考虑s[i+1...j]形成回文串的花费
dp[i][j]=min{dp[i][j],dp[i][j-1]+min(a[s[j]],b[s[j]])}考虑删除s[j]或者在i+1处添加s[j],都只用再考虑s[i...j-1]形成回文串的花费
初始化dp[i][i]=0 (1<=i<=m)其他值都为INF

需要优化递推式

POJ 1742: Coins ✓
多重部分和问题
记硬币的价值为a[i],个数为c[i],dp[i][j]为第i种硬币,合成j元时,第i种硬币的最大剩余,若dp[i][j]>=0则说明和可以合成j元
if (dp[i-1][j]>=0) dp[i][j]=c[i]
else if (j<a[i]) dp[i][j]=-1
else dp[i][j]=max{-1,dp[i][j-a[i]]-1}
初始化dp[i][0]=c[i]其他全部为-1
最后数满足dp[n][j]>=0 (1<=j<=m)的个数,复杂度O(N*M)
注:观察dp方程,发现第一维可以直接省去

POJ 3046: Ant Counting ✓ ☆
多重集组合数
记第i种蚂蚁有a[i]个,为不重复计数,一种蚂蚁最好一次性处理好
dp[i][j]为前j种蚂蚁,每个集合有i个蚂蚁的不同集合的个数(换种说法,从前j种蚂蚁中取i个蚂蚁的组合数)
dp[i][j]=∑{dp[i-k][j-1]:0<=k<=max(i,a[j])},复杂度O(ATN),需要优化递推式
通过找和dp[i-1][j]的关系,不难得出
if (i<a[j]+1) dp[i][j]=dp[i-1][j]+dp[i][j-1]
else dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-a[j]-1][j]
初始化:dp[0][i]=1 (0<=i<=T),每个集合都是空集,故只有一个集合,复杂度O(A*T)

POJ 3181: Dollar Dayz ✓
考虑花费为i,购买前j个工具的方案数
dp[i][j]=∑{dp[i-j*k][j-1]:0<=k<=⌊i/j⌋}
考虑用dp[i-j][j]优化递推式,不难得出
dp[i][j]=dp[i-j][j]+dp[i][j-1]
初始化:dp[0][i]=1 (1<=i<=m),复杂度O(N*K),这题离谱在于要用高精度(看半天以为dp错了),自己手搓一个吧!

有点意思的题

POJ 1065: Wooden Sticks ✓
经典题
结论:数列划分为的不降子序列最少的个数=最长严格下降子序列的长度,数列划分为不增子序列最少的个数=最长严格上升子序列的长度
于是这道题只需先按第一权值从小到大排序,求出第二权值的最长严格下降子序列的长度,而最长严格下降子序列=倒序查找最长严格上升子序列
dp[i]为长度为i的最长严格上升子序列末尾元素的最小值
顺序考虑第j个元素,如果j=1,则dp[1]=a[j],否则查找满足dp[i]>=a[j]的位置i,更新dp[i]=a[j]
由于dp数组是严格单增的,可以直接二分找到i,复杂度O(nlogn)
注:上述结论可以将不降子序列换为严格上升子序列,右侧等号换为最长不增子序列
求最长不降子序列的方法和求严格单增子序列方法一致,只需将>=换为>即可

POJ 1631: Bridging signals ✓
转换为求最长上升子序列即可,解法和上题一致。

POJ 3666: Making the Grade ☆
原数组记为a[],将a中数字哈希后记为hsh[]
开始猜到是二维dp,但不清楚第二维的含义,查看题解后,发现数字的改变一定是变为a[]中的某一个数字,故最多只有N个
dp[i][j]为序列1~i转换为以数字j结尾的不降序列的最小花费
dp[i][j]=min{dp[i][k]:k<=j}+abs(a[i]-hsh[j])
ans=min{dp[n][j]:j<=n}
若要考虑不增序列,只需要将a[]翻转后再计算dp即可
注:dp的第一维可以消去,可以通过维护最小前缀消去min函数,减少一层循环,复杂度O(N^2)

POJ 2392: Space Elevator ✓
多重部分和问题,和poj1742类似,只有某种方块的高度限制,贪心先按照方块的高度限制从小到大排序后,再dp即可

POJ 2184: Cow Exhibition ✓
记第i头牛的smartness值为a[i],funness值为b[i]
由于数据量较小,而且有双变量影响,故考虑将一个变量作为dp中的一维
dp[i][j]为前i头牛TS(total smartness)=j时,TF(total funness)的最大值
dp[i][j]=max{dp[i][j],dp[i][j-a[i]]+b[i]:1<=j-a[i]<=m},m为最大可能的TS值,不超过1e4
由于TS值最终要求是非负数,则先将a[]从大到小排序,再进行dp即可
ans=max{dp[n][j]+j:dp[n][j]>=0}
注:观察dp方程,发现可以通过改变j的枚举顺序(如果a[i]>0则倒序枚举,否则正序枚举),从而直接将第一维直接省去

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值