Dynamic Programming - HDU

最近主要刷一下动态规划专题,题目来自于HDU。

HDU 2955

这是一道概率DP,我第一次的想法是把概率P乘以100,变成一个背包然后做0-1背包,后来发现这样做是错误的。

原因:概率应该是相乘,而不是相加。

后来看了题解想到了另外一种方法,使用逃脱概率来计算,用f[j]表示偷走j价值后逃脱的概率。易知,多次逃脱概率为每次逃脱概率相乘。

由于要计算逃脱概率,我们可以在读入的时候就把可能被逮捕的概率P变成可能逃脱的概率1 - P。

这样,状态转移方程为:f[j] = max(f[j - pValue[i]] * pCost[i], f[j])。其中pValue[i]表示第i个银行的价值,pCost[i]表示偷第i个银行逃脱的概率。

这时候,我们还需要考虑一个转移条件,如果f[j - pValue[i]]没有被更新过,那么是不能转移过来的。因为暂时没有一个状态可以偷到j - pValue[i]价值的物品。

接下来,我们要考虑一下初始条件,很显然f[0] = 1,因为不偷任何东西,就不会被逮捕,逃脱的概率就为1。其余f[j] = -1,其中j ≠ 0,表示暂时没有一个状态可以偷到j价值的物品。

最后扫一遍f[j],满足1 - f[j] <= P的最大下标j为满足题设条件的答案。

#include <iostream>
#include <memory.h>

using namespace std;

const int MAX = 10240;

int pValue[MAX];
double pCost[MAX], f[MAX];

int main()
{
	int T, M, V;
	double P;
	cin >> T;
	for(int k = 1; k <= T; k++)
	{
		f[0] = 1; V = 0;
		for(int i = 1; i < MAX; i++)
		{ f[i] = -1; }
		cin >> P >> M;
		for(int i = 1; i <= M; i++)
		{
			cin >> pValue[i] >> pCost[i];
			pCost[i] = 1 - pCost[i];
			V += pValue[i];
		}
		for(int i = 1; i <= M; i++)
		{
			for(int j = V; j >= pValue[i]; j--)
			{
				if(f[j - pValue[i]] != -1)
				{ f[j] = max(f[j - pValue[i]] * pCost[i], f[j]); }
			}
		}
		int ans = 0;
		for(int i = 0; i <= V; i++)
		{
			if(1 - f[i] <= P)
			{ ans = i; }
		}
		cout << ans << endl;
	}
	return 0;
}

接触的第一道概率DP,发现DP非常的灵活,自己还有很多东西要学。 

2015年3月14日

【未完待续...】

时间: 2024-10-07 09:45:45

Dynamic Programming - HDU的相关文章

HDU 4972 A simple dynamic programming problem(推理)

HDU 4972 A simple dynamic programming problem 题目链接 推理,会发现只有前一个和当前一个分数为(1, 2)或(2, 1)的时候,会有两种加分方法,其他情况最多就一种情况,所以只要统计(1, 2),(2, 1)的个数,最后判断分差是否为0,如果不为0,那么可能是正或负,那就是两倍 代码: #include <cstdio> #include <cstring> const int N = 100005; int t, n, a[N]; i

hdu 4972 A simple dynamic programming problem(高效)

题目链接:hdu 4972 A simple dynamic programming problem 题目大意:两支球队进行篮球比赛,每进一次球后更新比分牌,比分牌的计数方法是记录两队比分差的绝对值,每次进球的分可能是1,2,3分.给定比赛中的计分情况,问说最后比分有多少种情况. 解题思路:分类讨论: 相邻计分为1-2或者2-1的时候,会对应有两种的的分情况 相邻计分之差大于3或者说相等并且不等于1的话,为非法输入 其他情况下,不会造成新的比分情况产生 对于最后一次比分差为0的情况,就没有谁赢谁

hdu 4972 A simple dynamic programming problem (转化 乱搞 思维题) 2014多校10

题目链接 题意:给定一个数组记录两队之间分差,只记分差,不记谁高谁低,问最终有多少种比分的可能性 分析: 类似cf的题目,比赛的时候都没想出来,简直笨到极点..... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <vector> 7 #include &

hdu 4223 Dynamic Programming?

Dynamic Programming? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Dynamic Programming, short for DP, is the favorite of iSea. It is a method for solving complex problems by breaking them down

HDU-4972 A simple dynamic programming problem

http://acm.hdu.edu.cn/showproblem.php?pid=4972 ++和+1还是有区别的,不可大意. A simple dynamic programming problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 307    Accepted Submission(s): 117 Problem D

Dynamic Programming

We began our study of algorithmic techniques with greedy algorithms, which in some sense form the most natural approach to algorithm design. Faced with a new computational problem, we've seen that it's not hard to propose multiple possible greedy alg

Dynamic Programming | Set 3 (Longest Increasing Subsequence)

在 Dynamic Programming | Set 1 (Overlapping Subproblems Property) 和 Dynamic Programming | Set 2 (Optimal Substructure Property) 中我们已经讨论了重叠子问题和最优子结构性质,现在我们来看一个可以使用动态规划来解决的问题:最长上升子序列(Longest Increasing Subsequence(LIS)). 最长上升子序列问题,致力于在一个给定的序列中找到一个最长的子序列

Dynamic Programming | Set 4 (Longest Common Subsequence)

首先来看什么是最长公共子序列:给定两个序列,找到两个序列中均存在的最长公共子序列的长度.子序列需要以相关的顺序呈现,但不必连续.例如,"abc", "abg", "bdf", "aeg", '"acefg"等都是"abcdefg"的子序列.因此,一个长度为n的序列拥有2^n中可能的子序列(序列中的每一个元素只有选或者不选两种可能,因此是2^n). Example: LCS for inp

2017 UESTC Training for Dynamic Programming

2017 UESTC Training for Dynamic Programming A    思维, 或 dp, 很有意思 方法1: 构造法:蛇形安排赛程表算法复杂度:O(N^2)将1-N排成两竖列,每一轮同一行的为对手保持1的位置不变,其他位置按顺(逆)时方向依次旋转1    6          1    2          1    3          1    4          1    5      2    5          3    6          4