acwing_4700_何以包邮

acwing_4700_何以包邮

acwing 4700. 何以包邮?

水一期

题目描述

新学期伊始,适逢顿顿书城有购书满 元包邮的活动,小 同学欣然前往准备买些参考书。

一番浏览后,小 初步筛选出 本书加入购物车中,其中第 本()的价格为 元。

考虑到预算有限,在最终付款前小 决定再从购物车中删去几本书(也可以不删),使得剩余图书的价格总和 在满足包邮条件()的前提下最小。

试帮助小 计算,最终选购哪些书可以在凑够 元包邮的前提下花费最小?

输入格式

输入的第一行包含空格分隔的两个正整数 ,分别表示购物车中图书数量和包邮条件。

接下来输入 行,其中第 行()仅包含一个正整数 ,表示购物车中第 本书的价格。

输入数据保证 本书的价格总和不小于

输出格式

仅输出一个正整数,表示在满足包邮条件下的最小花费。

数据范围

的测试数据满足:
全部的测试数据满足:,每本书的价格

输入样例1:

1
2
3
4
5
4 100
20
90
60
60

输出样例1:

1
110

样例1解释

购买前两本书 即可包邮且花费最小。

输入样例2:

1
2
3
4
3 30
15
40
30

输出样例2:

1
30

样例2解释

仅购买第三本书恰好可以满足包邮条件。

输入样例3:

1
2
3
2 90
50
50

输出样例3:

1
100

样例3解释

必须全部购买才能包邮。

dfs法

算是复习一下,优化一下能拿70

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<iostream>
#include<cstring>
using namespace std;

const int N = 50;
#define inf 0x3f3f3f3f

int n, m;
int a[N], minn = inf;
bool flag[N];

void dfs(int now)
{
if(now >= m)
{
minn = min(minn, now);
return;
}
for(int i = 1; i <= n; i ++)
{
if(flag[i] == false)
{
flag[i] = true;
dfs(now + a[i]);
flag[i] = false;
}
}
}

int main()
{
memset(flag, false, sizeof(flag));
cin >> n >> m;
for(int i = 1; i <= n; i ++)
cin >> a[i];
dfs(0);
cout << minn << endl;
return 0;
}

状压法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include<iostream>
#include<cstring>
using namespace std;

const int N = 50;
const int inf = 1e8;

int n, m;
int a[N], minn = inf;

int main()
{

cin >> n >> m;
for(int i = 0; i < n; i ++)
cin >> a[i];

for(int i = 0; i <= 1 << n; i ++)
{
int sum = 0;
for(int j = 0; j < n; j ++)
{
if(i >> j & 1)
{
sum += a[j];
}
}
if(sum >= m)
{
minn = min(minn, sum);
}

}

cout << minn << endl;
return 0;
}

动规法

类似于01背包,但要求选取的所有物品价值总和越小越好。01背包要求不大于某个数。

则可以转化为选取总和小于sum - x,越大越好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<iostream>
#include<cstring>
using namespace std;

const int N = 50;
const int M = 3000010;
const int inf = 1e8;

int n, m, sum, re;
int a[N], minn = inf;
int v[M];

int main()
{

cin >> n >> m;
for(int i = 1; i <= n; i ++)
cin >> a[i], sum += a[i];
re = sum - m;
for(int i = 1; i <= n; i ++)
{
for(int j = re; j >= a[i]; j --)
{
v[j] = max(v[j - a[i]] + a[i], v[j]);
}
}

cout << sum - v[re] << endl;
return 0;
}