题目链接在这儿:链接说明
题意:中文题
思路:
为什么不能用深搜+减脂?
尝试了一发,果然TLE了,因为理论上是2^50次方的运算。
有一个小小减脂是:后缀和,如果当前的值加后面所有的值不超过当前记录的最大值,就返回。
超时代码也贴一下:
#include <bits/stdc++.h> using namespace std; const int maxn = 55; int n, k, m; int a[maxn]; int sumafter[maxn]; int flag; void dfs(int step, int sum){ if (sum + sumafter[step] <= flag) return; if (flag == m) return; if (sum + sumafter[step] <= m){ flag = max(flag, sum + sumafter[step]); return; } if (step == n + 1){ flag = max(flag, sum); return; } if (sum - a[step] >= 0) dfs(step + 1, sum - a[step]); if (sum + a[step] <= m) dfs(step + 1, sum + a[step]); return; } int main(){ //freopen("input.txt", "r", stdin); flag = -1; scanf("%d%d%d", &n, &k, &m); memset(a, 0, sizeof(a)); memset(sumafter, 0, sizeof(sumafter)); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = n; i >= 1; i--) sumafter[i] = sumafter[i + 1] + a[i]; dfs(1, k); printf("%d\n", flag); return 0; }
超时了说明时间不够,那就拿空间来凑。把所有数据记录下来。
data[i][j]表示当弹奏到第 i 个时,是否可以达到 j 的音量。
根据初始数据,i这一维变量最大为 50,j这一维变量最大为 1000,数组合理。
复杂度呢?
data[i][j]可以根据data[i-1]的数据来算,而且不需要开 int 值,开 bool 值即可。
初始化是 data[0][初始音量值] = 1,其他都为 0。
说是dp,理解就是第 i 阶段的所有数据可以由第 i-1 阶段的所有数据推出来。我个人理解这个题是打表,把合法的数据全部打出来,存在就是1,不存在就是0。
代码如下。
#include<bits/stdc++.h> using namespace std; bool data[55][1050]; int n, k, m; int a[1050]; int flag; int main(){ //freopen("input.txt", "r", stdin); scanf("%d%d%d", &n, &k, &m); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); memset(data, 0, sizeof(data)); data[0][k] = 1; for(int i = 1; i <= n; i++) for(int j = 0; j <= m; j++) if (data[i-1][j] == 1){ if (j + a[i] <= m) data[i][j + a[i]] = 1; if (j - a[i] >= 0) data[i][j - a[i]] = 1; } flag = -1; for(int j = m; j >= 0; j--) if (data[n][j]){ flag = j; break; } printf("%d\n", flag); return 0; }