您的位置:首页 > 其它

hud上的动态规划练习

2017-06-30 19:47 239 查看
1、hud 2955 Robberies

(转载,你会发现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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: