1 Star 0 Fork 1

TheKernel/SJTU

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
min_subarray_sum_difference.cpp 3.32 KB
一键复制 编辑 原始数据 按行查看 历史
youlizhou 提交于 2021-04-25 19:32 . init
#include<stdio.h>
#include<string.h>
// 处理字符串, string -> int
int handle(char s[], int a[]){
int count = 0; // 计算处理完字符串后有几个数字(即整数数组大小)
int i = 0;
while(s[i] != '\0') {
if(s[i] >= '0' && s[i] <= '9') { // 假如我们遇到了数字,那么接下来处理这个数字
while(s[i] >= '0' && s[i] <= '9') { //可以用while直接处理完这串数字
a[count] = a[count] * 10 + (s[i]-'0');
i++;
}
count++; //整数数量加一
continue; //注意,处理到非数字后才结束,所以接下来这个字符未被判断是否合法,所以跳过下面的i++过程
}
else if(s[i] != ' ' && s[i] != '\n') return 0; //处理完数字,剩下的只可能是空格,注意,还可能是最后的换行符。如果不是这两个,那么就是非法的,返回0
i++;
}
for(int i = 0; i < count; i++)
if(a[i] == 0) return 0;
return count;
}
void qs(int low, int high, int a[]) { //快速排序算法。把数组从大到小进行排序。至于为什么从大到小,在dfs中剪枝的地方会说明
if(low >= high) return;
int i = low, j = high;
int val = a[i];
while(i < j) {
while(i < j && a[j] <= val) j--;
a[i] = a[j];
while(i < j && a[i] > val) i++;
a[j] = a[i];
}
a[i] = val;
qs(low, i-1, a);
qs(i+1, high, a);
}
int max(int a,int b){
return a > b ? a : b;
}
int a[50000];//为了方便写DFS,我把这些写为全局变量。全局变量还有一个好处就是,数组可以开的稍微大点
int ans;//用来存储小于等于sum/2的最大子序列的和
int n;//整数数组的大小
int half;//half=sum/2
void dfs(int i, int sum) {
if(i>=n || sum+(n-i)*a[i]<ans)
return;//剪枝啊剪枝。
//sum+(n-i)*a[i]<ans这个剪枝意思是:因为我a数组是从大到小排序,接下来啊a[i]...a[n-1]中任意一个最大也是a[i],
//那么如果我当前子序列和sum加上剩下的所有n-i个数最大也是sum+(n-i)*a[i],如果这个数还<当前暂存在ans中的子序列和,
//那么不需要继续往下加了,因为不可能得到比当前ans大的数。
//这个剪枝非常巧妙,且随着ans的更新会变得更为有效。我之前并没有加这个剪枝,结果超时了(当然,也可能是之前写错了)
if(sum+a[i]<=half){//只有不超过half,当前数a[i]才可能被加
ans=max(ans,sum+a[i]);//只有新加入a[i],ans才可能被更新
dfs(i+1,sum+a[i]);
}
dfs(i+1,sum);
}
int main()
{
char s[50000];//因为题目的输入原因,用字符串处理
while(fgets(s,50000,stdin)!=NULL){
memset(a,0,sizeof(a));//初始化整数数组a
n=handle(s,a);
if(!n){//如果n返回0,就是非法的
printf("ERROR\n");
continue;//别忘了,或者下面的过程加个else
}
int sum=0;//数组a的和
for(int i=0;i<n;i++)sum+=a[i];
half=sum/2;//根据sum的值算出half
qs(0,n-1,a);//排序
ans=0;//初始化小于等于half的最大子序列和
dfs(0,0);
printf("%d %d\n",sum-ans,ans);//题目要求降序输出。ans算出的是比sum一半小的,那么sum-ans应该比sum一半大
}
return 0;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/TheKernel/sjtu.git
git@gitee.com:TheKernel/sjtu.git
TheKernel
sjtu
SJTU
master

搜索帮助