您的位置:首页 > 其它

dp专题-简单基础dp-背包

2016-03-01 20:51 344 查看
按照这个做的:http://doc.okbase.net/cc_again/archive/71796.html

hdu
1864 最大报销额 01背包
方法一:
double类型的背包
总数30个、每个最大1000、保留2位有效位。直接把double*100转换为int型的背包
代码

//看清题目
//double型的01背包
#include
#include
#include
using namespace std;

const int N = 3000050;
int dp
;
int a
;

int main(void)
{
double total;
int n;
int i, j;
while(scanf("%lf%d", &total, &n), n)
{
int tmp;
int cnt = 0;
memset(dp, 0, sizeof(dp));
for(j = 0; j < n; j++)
{
scanf("%d", &tmp);
//            cin >> tmp;
double pricetotal = 0.0;
char c, cc;
double price;
int flag = 1;
double A, B, C;
A = B = C = 0;
for(i = 0; i < tmp; i++)
{
char c;
getchar();
scanf("%c:%lf", &c, &price);
if(c == 'A' && A+price <= 600.0)
{
A  += price;
}
else if(c == 'B' && B+price <= 600.0)
{
B += price;
}
else if(c == 'C' && C+price <= 600.0)
{
C += price;
}
else
flag = 0;
}

if(flag && A+B+C <= 1000.0)
a[cnt++] = (A+B+C)*100;

}
int v = (total)*100;
for(i = 0; i < cnt; i++)
{
for(j = v; j >= a[i]; j--)
{
dp[j] = max(dp[j], dp[j-a[i]]+a[i]);
}
}
double ans = dp[v];
printf("%.2lf\n", ans/100.0);
}
return 0;
}


对个数背包,dp[j] = max(dp[j], dp[j-1]+a[i]);

网上的代码能ac但错了的代码,有后效性

这组就过不了

100.00 5
1 A:5
1 B:20
1 C:24
1 A:30
1 A:60

#include
#include
#include
using namespace std;

const int N = 100;
double a
;
double dp
;

void debug(int n, double a[])
{
for(int i = 0; i < n; i++)
{
printf("%.2lf  ", a[i]);
}
printf("\n");
}

int main(void)
{
double total;
int n;
while(~scanf("%lf%d", &total, &n), n)
{
int i, j;
int cnt = 0;
memset(a, 0, sizeof(a));
memset(dp, 0, sizeof(dp));
for(i = 0; i < n; i++)
{
int tmp  = 0;
int flag = 1;
scanf("%d", &tmp);
char c;
double price;
double A, B, C;//三类的总价格
A = B = C = 0;
while(tmp--)
{
getchar();
scanf("%c:%lf", &c, &price);
if(c == 'A' && price+A <= 600.0)
{
A += price;
}
else if(c == 'B' && price+B <= 600.0)
{
B += price;
}
else if(c == 'C' && price+C <= 600.0)
{
C += price;
}
else
flag = 0;
}
if(flag && A+B+C <= 1000.0)
{
a[cnt++] = A+B+C;
}
}
for(i = 0; i < cnt; i++)
{
for(j = cnt; j >= 1; j--)
{
if(dp[j-1]+a[i] <= total)
dp[j] = max(dp[j], dp[j-1]+a[i]);
}
}
double ans = 0;
for(i = 0; i <= cnt; i++)
ans = max(ans, dp[i]);
printf("%.2lf\n", ans);
}

return 0;
}


方法二:
搜索

//dfs+剪枝
#include
#include
#include
#include
using namespace std;

const int N = 100;
double a
;
double sum
;

double dfs(double total, int cnt)
{
double ans;
if(cnt == 1) return a[cnt]>total?0:a[cnt];
if(total >= sum[cnt]) return sum[cnt];//剪枝关键,否者时间复杂度为O(2^n)

if(a[cnt] == total) ans = a[cnt];
else if(a[cnt] < total)
{
ans = max(dfs(total-a[cnt], cnt-1)+a[cnt], dfs(total, cnt-1));
}
else
ans = dfs(total, cnt-1);
return  ans;
}

int main(void)
{
double total;
int n;
int i, j;
while(scanf("%lf%d", &total, &n), n)
{
int tmp;
int cnt = 1;
memset(sum, 0, sizeof(sum));

for(j = 0; j < n; j++)
{
scanf("%d", &tmp);
double pricetotal = 0.0;
char c, cc;
double price;
int flag = 1;
double A, B, C;
A = B = C = 0;
for(i = 0; i < tmp; i++)
{
char c;
getchar();
scanf("%c:%lf", &c, &price);
if(c == 'A' && A+price <= 600.0)
{
A  += price;
}
else if(c == 'B' && B+price <= 600.0)
{
B += price;
}
else if(c == 'C' && C+price <= 600.0)
{
C += price;
}
else
flag = 0;
}

if(flag && A+B+C <= 1000.0)
a[cnt++] = (A+B+C);
}
for(i = 1; i < cnt; i++)
{
sum[i] = sum[i-1] + a[i];
}
printf("%.2lf\n", dfs(total, cnt-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: