hud上的动态规划练习
2017-06-30 19:47
239 查看
1、hud 2955 Robberies
(转载,你会发现dp下标是什么以及内容存储什么是很重要的)
第一点就是最容易犯错的一点,把所求总被抓概率看成背包容量。这就有两个很明显错误,求的就是1-被抓概率=逃跑概率,限制条件和最大背包容量不能同为一属性。再者,概率为多为浮点数,精确度不高无法遍历。所以背包容量必然是钱数,因为他能抢的银行有限,钱数也是有限的。然后是求最大逃跑概率,而题中每项给出的是被抓概率,所以要先被1减一下。还有最后求得的逃跑概率随着抢银行的数量增加而减少,多抢一个银行,其钱数必将转化为概率的乘积,所以动态方程也要做出改变。最后遍历,剩余的钱数越多,说明所抢的钱数越少,逃跑几率越大。所以从大到小遍历背包容量,一旦大于p,即为最大概率跳出。
2、hud 1864 最大报销额
最主要的是将数据扩大100倍 dp[j]=max(dp[j],dp[j-v[i]]+v[i])
3、hdu 1231 最大连续子序列
4、hdu 1506 Largest Rectangle in a Histogram
最开始我想的是每一个都去比较一下,结果超时了
结果看了网上的别人的代码才发现,dp[i]每次记录的是包含i矩形的最大值即可。
最主要的还是引进了L数组和R数组,类似于find_union的思想;
这个代码之前写错了,应该是j
(转载,你会发现dp下标是什么以及内容存储什么是很重要的)
第一点就是最容易犯错的一点,把所求总被抓概率看成背包容量。这就有两个很明显错误,求的就是1-被抓概率=逃跑概率,限制条件和最大背包容量不能同为一属性。再者,概率为多为浮点数,精确度不高无法遍历。所以背包容量必然是钱数,因为他能抢的银行有限,钱数也是有限的。然后是求最大逃跑概率,而题中每项给出的是被抓概率,所以要先被1减一下。还有最后求得的逃跑概率随着抢银行的数量增加而减少,多抢一个银行,其钱数必将转化为概率的乘积,所以动态方程也要做出改变。最后遍历,剩余的钱数越多,说明所抢的钱数越少,逃跑几率越大。所以从大到小遍历背包容量,一旦大于p,即为最大概率跳出。
#include <stdio.h> #include <algorithm> #include <iostream> #include <cmath> #include <string.h> using namespace std; const int N = 50005; int main() { // freopen("in.txt", "r", stdin); int t, m0, m ; double p0, p , ans ; scanf("%d", &t); while(t --) { scanf("%lf%d", &p0, &m0); int sum = 0; for(int i = 0; i < m0; i ++) { scanf("%d%lf", &m[i], &p[i]); sum += m[i]; } memset(ans, 0, sizeof(ans)); ans[0] = 1; for(int i = 0; i < m0; i ++) { for(int j = sum; j >= m[i]; j --) { ans[j] = max(ans[j], ans[j - m[i]] *(1 - p[i])); } } for(int i = sum; i >= 0; i --) { if(ans[i] > (1 - p0)) { printf("%d\n", i); break; } } } return 0; }
2、hud 1864 最大报销额
最主要的是将数据扩大100倍 dp[j]=max(dp[j],dp[j-v[i]]+v[i])
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<algorithm> #define MAXNUM 3000050 using namespace std; int N, dp[MAXNUM], bill[35]; float sum; int main() { //freopen("1.txt", "r", stdin); int i, j, k, t, res, total, n[3]; char c; float cash; bool flag; while (scanf("%f%d", &sum, &N) != EOF&&N) { memset(dp, 0, sizeof(dp)); memset(bill, 0, sizeof(bill)); total = (int)(100 * sum); t = 0; for (i = 0; i < N; i++) { memset(n, 0, sizeof(n)); flag = 1; scanf("%d", &k); for (j = 0; j < k; j++) { scanf(" %c:%f", &c, &cash); if (c == 'A' || c == 'B' || c == 'C') n[c - 'A'] += (int)(cash * 100); else flag = 0; } res = n[0] + n[1] + n[2]; if (n[0] <= 60000 && n[1] <= 60000 && n[2] <= 60000 && flag&&res<=100000) bill[t++] = res; } for (i = 0; i < t; i++) { for (j = total; j >= bill[i]; j--) { dp[j] = max(dp[j - bill[i]] + bill[i], dp[j]); } } printf("%.2f\n", float(float(dp[total]) / 100)); } return 0; }
3、hdu 1231 最大连续子序列
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<algorithm> #define MAXNUM 10010 using namespace std; int N, dp[MAXNUM], start[MAXNUM], num[MAXNUM]; int main() { //freopen("1.txt", "r", stdin); int i, j, k, t, ans, total, end; bool flag; while (scanf("%d", &N) && N) { memset(dp, 0, sizeof(dp)); memset(start, 0, sizeof(start)); memset(num, 0, sizeof(num)); flag = 1; for (i = 1; i <= N; i++) { scanf("%d", &num[i]); if (flag&&num[i] >= 0) flag = 0; } if (flag) { printf("0 %d %d\n", num[1], num ); continue; } ans = dp[1] = num[1]; start[1] = 1; end = 1; for (i = 2; i <= N; i++) { if (dp[i - 1] >= 0) { start[i] = start[i - 1]; dp[i] = num[i] + dp[i - 1]; } else { start[i] = i; dp[i] = num[i]; } if (dp[i] > ans) { ans = dp[i]; end = i; } } printf("%d %d %d\n", ans, num[start[end]], num[end]); } return 0; }
4、hdu 1506 Largest Rectangle in a Histogram
最开始我想的是每一个都去比较一下,结果超时了
for (i = 2; i <= N; i++) { dp[i] = tmp = num[i]; t = 1; for (j = i - 1; j >= 1; j--) { tmp = min(tmp, num[j]); dp[i] = max(dp[i], tmp*(++t)); } ans = max(dp[i], ans); }
结果看了网上的别人的代码才发现,dp[i]每次记录的是包含i矩形的最大值即可。
最主要的还是引进了L数组和R数组,类似于find_union的思想;
while (num[i] <= num[j + 1] &&j < N) j = R[j + 1];
这个代码之前写错了,应该是j
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#define MAXNUM 100010
using namespace std;
int N;
long long num[MAXNUM], L[MAXNUM], R[MAXNUM];
int main()
{
freopen("1.txt", "r", stdin);
int i, j, k, t, l, r;
long long ans, tmp;
while (scanf("%d", &N)!=EOF && N)
{
for (i = 1; i <= N; i++)
{
scanf("%lld", &num[i]);
}
L[1] = 1;
R
= N;
for (i = 2; i <= N; i++)
{
j = i;
while (num[j - 1] >= num[i] && j > 1)
j = L[j - 1];
L[i] = j;
}
for (i = N-1; i >= 1; i--)
{
j = i;
while (num[i] <= num[j + 1] &&j < N) j = R[j + 1];
R[i] = j;
}
ans = 0;
for (i = 1; i <= N; i++)
{
tmp = (R[i] - L[i] + 1)*num[i];
if (tmp > ans)
ans = tmp;
}
printf("%lld\n", ans);
}
return 0;
}
相关文章推荐