题目链接在这儿:链接说明
题意:中文题
思路:
为什么不能用深搜+减脂?
尝试了一发,果然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;
}



京公网安备 11010502036488号