dp

P1073 最优贸易 DAG dp入门

六月ゝ 毕业季﹏ 提交于 2020-03-10 22:11:04
题目描述 C 国有n 个大城市和m 条道路,每条道路连接这n 个城市中的某两个城市。任意两个城市之间最多只有一条道路直接相连。这m 条道路中有一部分为单向通行的道路,一部分为双向通行的道路,双向通行的道路在统计条数时也计为1条。C 国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同。但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。商人阿龙来到 C 国旅游。当他得知同一种商品在不同城市的价格可能会不同这一信息之后,便决定在旅游的同时,利用商品在不同城市中的差价赚回一点旅费。 设C 国n 个城市的标号从1~ n,阿龙决定从1 号城市出发,并最终在n 号城市结束自己的旅行。在旅游的过程中,任何城市可以重复经过多次,但不要求经过所有n 个城市。阿龙通过这样的贸易方式赚取旅费:他会选择一个经过的城市买入他最喜欢的商品——水晶球,并在之后经过的另一个城市卖出这个水晶球,用赚取的差价当做旅费。由于阿龙主要是来C 国旅游,他决定这个贸易只进行最多一次,当然,在赚不到差价的情况下他就无需进行贸易。 假设 C 国有5 个大城市,城市的编号和道路连接情况如下图,单向箭头表示这条道路 为单向通行,双向箭头表示这条道路为双向通行。假设 1~n 号城市的水晶球价格分别为4,3,5,6,1。阿龙可以选择如下一条线路:1->2->3->5,并在2 号城市以3

3/8每日一题_零钱兑换

风格不统一 提交于 2020-03-10 09:38:02
#322 零钱兑换 解题思路: 一开始看到这道题,便立马想到了是否存在最优子结构,以示例1来说,amount=11,可以由求解amount=10的解再加上面额为1的硬币得到,然而求解amount=9的解应该为{5,2,2},而amount=10的解应该为{5,5},所以并不可以从amount=9的最优解得到amount=10的的最优解,因为之前用动态规划解决问题,都是前一步推后一步,对于现在这种情况并不适用(其实是我没想到),动态规划陷入了僵局。 然后,模拟了一下示例1的求解步骤: ①{5},5<11; ②{5,5},5+5=10<11; ③{5,5,5},5+5+5=15>11; ④{5,5,2},5+5+2=12>11; ⑤{5,5,1},5+5+1=11=11,结束。 这不就是回溯法吗?! 能进则进,进不了则换,换不了则退 ! 经过我不懈努力,花费了大量时间,还是没写出来(我承认,我太菜了)。 但是,这两个思路还是很正确的! 解题方法 动态规划,自下而上方法(官方方法): 其实这个问题很像青蛙跳台阶,每次可以跳1级、2级和5级,问跳上n级最少需要跳多少次? 以前问的是有多少种跳法:F(n)=F(n-1)+F(n-2)+F(n-5) ,现在问的是,最少需要跳多少次,要从前一个子解中找最小值,所以 F(n)=min{F(n-1),F(n-2),F(n-5)}+1 ,需要+1是因为

关于dfs dp 递归的整理

守給你的承諾、 提交于 2020-03-09 12:51:25
三者有交集但是不太一样; 递归是一种通用方法,有些问题可以采用纯递归解决,但是需要问题分解; 分解过程主要需要一个递归表达式; 也就是典型的某一种情况是前一种情况的组合; dp问题主要还是找公共子问题,最重要的是他和递归不一样在于其在递归的思路上解决了重复计算的问题; dfs问题就是搜索,从头向下搜,以前研究过,前面博文有; 来源: https://www.cnblogs.com/songlinxuan/p/12447958.html

分割整数的最大乘积

五迷三道 提交于 2020-03-09 08:49:54
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 示例 1: 输入: 2 输出: 1 解释: 2 = 1 + 1, 1 × 1 = 1。 示例 2: 输入: 10 输出: 36 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。 说明: 你可以假设 n 不小于 2 且不大于 58。 1 public class T343 { 2 public int integerBreak(int n) { 3 int[] dp = new int[n + 1]; 4 Arrays.fill(dp, 1); 5 for (int i = 3; i <=n ; i++) { 6 for (int j = 1; j < i; j++) { 7 dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j])); 8 } 9 } 10 return dp[n]; 11 } 12 } 来源: https://www.cnblogs.com/zzytxl/p/12446663.html

LeetCode 322. 零钱兑换

久未见 提交于 2020-03-09 04:52:37
322. 零钱兑换 给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。 示例 1: 输入: coins = [1, 2, 5], amount = 11 输出: 3 解释: 11 = 5 + 5 + 1 思路:dp[i]=x表示amount为i至少需要x个硬币,初始化dp[i]=amount+1,然后dp[i] = min(dp[i], dp[i-coin]+1); class Solution { public: int coinChange(vector<int>& coins, int amount) { vector<int> dp(amount+1, amount+1); dp[0] = 0; for(int i=1;i<=amount;i++){ for(int coin: coins){ if (i - coin < 0) continue; dp[i] = min(dp[i], dp[i-coin]+1); } } return dp[amount]==amount+1?-1:dp[amount]; } }; 来源: CSDN 作者: vision泉 链接: https://blog.csdn.net/weixin_38603360/article

leetcode 不同路径II

匆匆过客 提交于 2020-03-09 04:37:48
1.动态规划 这道题和前一题基本一样,状态转移方程仍然是 dp[i][j]=dp[i-1][j-1]+dp[i][j-1]. 区别在于当i,j不可达时,其值为0,且需要首先初始化dp的边界值。 代码如下: class Solution { public: int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) { int m=obstacleGrid.size(),n=obstacleGrid[0].size(); vector<vector<int>>dp(m,vector<int>(n,0));//初始化为0 //首先初始化边界 //上边界,障碍物及其后的位置都不可达 for(int i=0;i<n;i++) if(obstacleGrid[0][i]==1) { for(int j=i;j<n;j++) dp[0][j]=0;// break; } else dp[0][i]=1; //左边界,障碍物及其下的位置都不可达 for(int i=0;i<m;i++) if(obstacleGrid[i][0]==1) { for(int j=i;j<m;j++) dp[j][0]=0;// break; } else dp[i][0]=1; for(int i=1;i<m;i++) for(int j=1;j

9.8---硬币问题(CC150)

邮差的信 提交于 2020-03-08 05:08:08
这道题卡了一天。要想AC非常难。 1,第一个解决办法,优化暴力: public class Coins { public static int countWays(int n){ int num25 = n / 25; long res = 0; for(int i = 0; i <= num25;i++){ int leave25 = n - i * 25; int num10 = leave25 / 10; for(int j = 0; j <= num10; j++){ int leave10 = leave25 - j * 10; int num5 = leave10 / 5; res += num5 + 1; res = res % 1000000007; } } return (int) res; } } View Code 2,第二个解决办法,递推式: 但是LTE。 dp[i][sum] = 用前i种硬币构成sum 的所有组合数。 http://www.cnblogs.com/python27/archive/2013/09/05/3303721.html public static int myCountWays(int n){ int[][] dp = new int[5][n+1]; int[] coins = {1,5,10,25}; for(int i =

HDU免费馅饼(DP)

徘徊边缘 提交于 2020-03-08 00:37:15
题目 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了,所以gameboy马上卸下身上的背包去接。但由于小径两侧都不能站人,所以他只能在小径上接。由于gameboy平时老呆在房间里玩游戏,虽然在游戏中是个身手敏捷的高手,但在现实中运动神经特别迟钝,每秒种只有在移动不超过一米的范围内接住坠落的馅饼。现在给这条小径如图标上坐标: 为了使问题简化,假设在接下来的一段时间里,馅饼都掉落在0-10这11个位置。开始时gameboy站在5这个位置,因此在第一秒,他只能接到4,5,6这三个位置中其中一个位置上的馅饼。问gameboy最多可能接到多少个馅饼?(假设他的背包可以容纳无穷多个馅饼) 输入格式 输入数据有多组。每组数据的第一行为以正整数n (0<n<100000) ,表示有n个馅饼掉在这条小径上。在结下来的n行中,每行有两个整数x,T (0<T<100000) ,表示在第T秒有一个馅饼掉在x点上。同一秒钟在同一点上可能掉下多个馅饼。n=0时输入结束。 输出格式 每一组输入数据对应一行输出。输出一个整数m,表示gameboy最多可能接到m个馅饼。 提示:本题的输入数据量比较大,建议用scanf读入,用cin可能会超时。 样例输入 6

2014百度之星资格赛 1004:Labyrinth(DP)

早过忘川 提交于 2020-03-06 09:49:12
Labyrinth Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1507 Accepted Submission(s): 520 Problem Description 度度熊是一只喜欢探险的熊,一次偶然落进了一个m*n矩阵的迷宫,该迷宫只能从矩阵左上角第一个方格开始走,只有走到右上角的第一个格子才算走出迷宫,每一次只能走一格,且只能向上向下向右走以前没有走过的格子,每一个格子中都有一些金币(或正或负,有可能遇到强盗拦路抢劫, 度度熊身上金币可以为负,需要给强盗写欠条 ),度度熊刚开始时身上金币数为0,问度度熊走出迷宫时候身上最多有多少金币? Input 输入的第一行是一个整数T(T < 200),表示共有T组数据。 每组数据的第一行输入两个正整数m,n(m<=100,n<=100)。接下来的m行,每行n个整数,分别代表相应格子中能得到金币的数量,每个整数都大于等于-100且小于等于100。 Output 对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。 每组测试数据输出一行,输出一个整数,代表根据最优的打法,你走到右上角时可以获得的最大金币数目。 Sample

HDU 1561 The more, The Better【树形DP】

只谈情不闲聊 提交于 2020-03-03 22:20:55
Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物。但由于地理位置原因,有些城堡不能直接攻克,要攻克这些城堡必须先攻克其他某一个特定的城堡。你能帮ACboy算出要获得尽量多的宝物应该攻克哪M个城堡吗? Input 每个测试实例首先包括2个整数,N,M.(1 <= M <= N <= 200);在接下来的N行里,每行包括2个整数,a,b. 在第 i 行,a 代表要攻克第 i 个城堡必须先攻克第 a 个城堡,如果 a = 0 则代表可以直接攻克第 i 个城堡。b 代表第 i 个城堡的宝物数量, b >= 0。当N = 0, M = 0输入结束。 Output 对于每个测试实例,输出一个整数,代表ACboy攻克M个城堡所获得的最多宝物的数量。 Sample Input 3 2 0 1 0 2 0 3 7 4 2 2 0 1 0 4 2 1 7 1 7 6 2 2 0 0 Sample Output 5 13 转:分析: 状态 dp[i][j] 为以 i 为根节点,选出 j 个节点的最大价值(包括 i 这个节点) 转移方程:dp[i][j]=max(dp[i1][j1]+dp[i2][j2]+....+dp[ik][jk])+a[i] j1+j2+...+jk=j