一、Problem
今年的世界冰球锦标赛在捷克举行。Bobek 已经抵达布拉格,他不是任何团队的粉丝,也没有时间观念。他只是单纯的想去看几场比赛。如果他有足够的钱,他会去看所有的比赛。不幸的是,他的财产十分有限,他决定把所有财产都用来买门票。
给出 Bobek 的预算和每场比赛的票价,试求:如果总票价不超过预算,他有多少种观赛方案。如果存在以其中一种方案观看某场比赛而另一种方案不观看,则认为这两种方案不同。
输入格式:
第一行,两个正整数 N 和 M(1≤N≤40,1≤M≤1018),表示比赛的个数和 Bobek 那家徒四壁的财产。
第二行,N 个以空格分隔的正整数,均不超过 1016,代表每场比赛门票的价格。
输出格式:
输出一行,表示方案的个数。由于 N 十分大,注意:答案 ≤ 240。
输入输出样例
输入样例#1:
5 1000
100 1500 500 500 1000
输出样例#1:
8
样例解释
八种方案分别是:
- 一场都不看,溜了溜了
- 价格 100 的比赛
- 第一场价格 500 的比赛
- 第二场价格 500 的比赛
- 价格 100 的比赛和第一场价格 500 的比赛
- 价格 100 的比赛和第二场价格 500 的比赛
- 两场价格 500 的比赛
- 价格 1000 的比赛
有十组数据,每通过一组数据你可以获得 10 分。各组数据的数据范围如下表所示:
二、Solution
比赛的个数正常,但是财产最大有 ,dp 数组也不可能开这么大…不然可以用 01 dp 把它 A 掉…
方法一:暴搜
- 对于某一场比赛,可看可不看…
- 最后遍历到最后一场比赛,res++
超时与溢出:16/100 分…
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
int N;
long[] a;
long res;
void dfs(int k, long m) {
if (m < 0)
return;
if (k == N) {
res++;
return;
}
dfs(k+1, m);
dfs(k+1, m-a[k]);
}
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
N = sc.nextInt();
int M = sc.nextInt();
a = new long[N];
for (int i = 0; i < N; i++) {
a[i] = sc.nextLong();
}
dfs(0, M);
System.out.println(res);
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,
方法二:01 背包
- 定义状态:
- 场次为 表示余额为 j 时,不考虑第 i 场比赛的方案数。
- 相反也很简单…
- 思考状态转移方程:
- 场次为 i,余额为 j 时, ,当余额为 j 时,我可选择看或不看第 i 场比赛…
- 思考初始化:
- dp[0] = 1,表示余额为 0 时,不看也是一种方案。
- 思考输出: 表示方案数位余额为 时的方案数之和。
溢出:32 分…
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
int N = sc.nextInt();
int m = sc.nextInt();
int[] a = new int[N+1];
long res = 0;
for (int i = 1; i <= N; i++) {
a[i] = sc.nextInt();
}
int[] dp = new int[m+1];
dp[0] = 1;
for (int i = 1; i <= N; i++) {
for (int j = m; j >= a[i]; j--)
dp[j] = dp[j] + dp[j-a[i]];
}
for (int i = 0; i <= m; i++)
res += dp[i];
System.out.println(res);
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,
方法三:折半搜索
…