#include <iostream>
#include <string>
#include <vector>
#include <numeric>
#include <bitset>
#include <algorithm>
#include <limits>
#include <functional>
using namespace std;
bool sto_vec(const string &str,vector<int>& vec){//把数组分离出来
int count =0;
for(int i(0);i<str.size();++i){
if(str[i]>='0' && str[i]<= '9')
count++;
else if(str[i] == ' ' && count !=0){
vec.push_back(stoi(str.substr(i-count,count)));
count=0;
}else
return false;
}
if(count>0)
vec.push_back(stoi(str.substr(str.size()-count,count)));
return true;
}
//方法一:时间复杂度2^n,需要减枝
int dp_func(int i,int j,const vector<int>& vec){ //递归模拟动态规划0-1背包,j为代价,时间复杂度太大,舍去;
if(i==0 || j==0) return 0;
auto temp (dp_func(i-1,j,vec));//先算不取这个值的,成功可能性大
if(j<vec[i] || temp == j){
return temp;
}else{
return max(temp,dp_func(i-1,j-vec[i],vec)+vec[i]);
}
}
//方法二:时间复杂度2^n,需要减枝
void dfs(int i,const int& half,int now_sum,const vector<int>& vec,int& ans){
if(i==vec.size()) return;
auto temp(now_sum+vec[i]);
if(temp == half){
ans =half;
return;
}else if(temp<half){
ans = max(ans,temp);
dfs(i+1,half,temp,vec,ans);//选中
if(ans == half)return;
}
//不选中
dfs(i+1,half,now_sum,vec,ans);
return ;
}
//方法三,参考大神们的;时间复杂度2^(n/2)。运行时间:40ms
//思想:把数组分成左右两半,左边(长度left)各种元素相加可能性有2^left种;右边有2^righ种;
//然后寻找所有可能性中,左边部分+右边部分小于等于half的最大值;
//我这儿为了思路清晰,把大神的许多优化去掉了
int solve(const vector<int>& vec,const int& half){
int len(vec.size());
int left(len/2);
int right(len-left);
int left_status(1<<left);//2^left
int right_status(1<<right);
bitset<32> assist;
vector<int>left_sum;//左半各种相加的可能性
for(int i(0);i<left_status;++i){
assist=i;
int temp =0;
for(int j(0);j<left;++j){
if(assist[j]){
temp += vec[j];
}
}
if(temp<=half){
left_sum.push_back(temp);
}
}
sort(left_sum.begin(),left_sum.end());
vector<int>right_sum;//右半各种相加的可能性
for(int i(0);i<right_status;++i){
assist=i;
int temp =0;
for(int j(0);j<right;++j){
if(assist[j]){
temp += vec[j+left];
}
}
if(temp<=half){
right_sum.push_back(temp);
}
}
//寻找左+右小于等于half且最接近half
int ans(numeric_limits<int>::min());
for(const auto& item:right_sum){
auto iter = upper_bound(left_sum.begin(), left_sum.end(), half - item);//*iter为left_sum中满足*iter>half - item的第一个值,既满足item + *(--iter)<=half的最大值;
if (iter != left_sum.begin()){
--iter;
ans = max(ans, item + *iter);
}
}
return ans;
}
int main(){
string str;
int ans;
while(getline(cin,str) && !str.empty()){
vector<int> vec;
if(!sto_vec(str,vec)){
cout<<"ERROR"<<endl;
continue;
}
int sum = accumulate(vec.begin(),vec.end(),0);
int half = sum/2;
//大的排前面能大大优化性能。对方法一、运行时间:185ms;小的排前为516ms。
//对方法二:运行时间:89ms;小的在前运行时间:238ms。
//对方法三:运行时间:35ms;小的在前运行时间:32ms,相差不大,小的在前貌似更优
//sort(vec.begin(),vec.end(),greater<int>());//方法一、二使用
//sort(vec.begin(),vec.end());//方法三使用
//方法一,递归模拟动态规划0-1背包,时间复杂度太大,运行时间:317ms
//sort(vec.begin(),vec.end(),greater<int>());
//vec.insert(vec.begin(),0);//第一个元素为0,占位,为了序号从1开始,不从0开始;
//ans = dp_func(vec.size()-1,half,vec);
//方法二
//sort(vec.begin(),vec.end(),greater<int>());
//dfs(0,half,0,vec,ans=0);
//方法三
sort(vec.begin(),vec.end());
ans = solve(vec,half);
cout<<sum-ans<<' '<<ans<<endl;
}
return 0;
} 三种方法:1、模拟0-1背包,2,深度优先搜索。两种时间复杂度都是2^n,都需要减枝。3划分为两半,参考大神的解法。提前排序能优化性能。时间复杂度待商榷
#include <iostream>
using namespace std;
bool isDigit(char c){ // 判断是否为数字
if(c>'9'||c<'0'){
return false;
}else{
return true;
}
}
int ch2num(char c){
return c-'0';
}
int max(int a,int b){
if(a>b) return a;
else return b;
}
int num[1000];// 先开1000试试
int idx =0;
bool flag; //判断是否为非法输入
int sum=0;
int half = 0;
int first =0; // 存储当前搜索最大结果
void init(){
first =0;
flag = false;
idx=0;
sum = half = 0;
}
void DFS(int i,int sum){
if(i==idx) return; // 搜索完全部数组内容结束
else if(sum + num[i]<=half){
first = max(sum+num[i],first);
if(first ==half) return ;
DFS(i+1,sum+num[i]);
}
DFS(i+1,sum);
}
int main(){
string s;
while(getline(cin,s)){
init();
int length = s.length();
for(int i=0;i<length;i++){
if(s[i]==' ') continue;
else{
int x = ch2num(s[i]);
if(isDigit(s[i])){
int j= i+1;
int temp =0;
temp = temp*10 + x;
while(isDigit(s[j])){
x = ch2num(s[j]);
temp = temp*10 + x;
j++;
}
num[idx++] = temp;
i = j;
}else{
flag = true;// 非法
}
}
}
if(flag){
cout << "ERROR"<<endl;
}else{
for(int i=0;i<idx;i++){
sum = sum + num[i];
}
half = sum/2;
DFS(0,0);
cout<<sum-first<<" "<<first<<endl;
}
}
return 0;
} #include<iostream>
(720)#include<vector>
#include<string>
using namespace std;
// dp 0-1 背包问题
void package(vector<int> &nums){
int n = nums.size() , sum = 0;
for(int num : nums) sum += num;
int target = sum/2;
// 不能重复时
vector<bool> dp(target + 1, 0);
dp[0] = true;
for(int num : nums){
for(int i = target; i >= num ; i--){
dp[i] = dp[i] || dp[i-num];
}
}
int b = 0;
for(int i= target; i >= 0; i--){
if(dp[i]) {b = i; break;}
}
printf("%d %d\n",b,sum-b);
}
int main()
{
string str ;
while (getline(cin,str))
{
bool ok = true;
for (int i = 0; i < str.size(); i++)
{
if (str[i] != ' ' && !(str[i] >= '0' && str[i] <= '9'))
{
ok = false;
break;
}
}
if (!ok)
{
cout << "ERROR" << endl;
continue;
}
vector<int> nums;
int prev = 0;
for (int i = 0; i < str.size(); i++)
{
char c = str[i];
if (c == ' ' )
{
nums.push_back(stoi(str.substr(prev,i-prev)));
prev = i + 1;
}
}
nums.push_back(stoi(str.substr(prev,str.size()-prev)));
package(nums);
}
return 0;
}
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
int d[100];
int j,min_sum,s1,s2,sum;
bool GetNum(string s)
{
j = 0;
sum = 0;
memset(d,0,sizeof(d));
for(int i = 0;i < s.size();i++)
{
if(s[i] == ' ')
{
j++;
continue;
}
if(s[i] >= '0' && s[i] <= '9')
d[j] = d[j] * 10 + s[i] - '0';
else return false;
}
j++;
for(int i = 0;i < j;i++) sum += d[i];
return true;
}
void DFS(int sum1,int i)
{
if(sum1 > sum / 2 || s1 == s2) return;
if(i == j)
{
if(abs(sum - sum1 * 2) < min_sum)
{
min_sum = abs(sum - sum1 * 2);
s1 = sum1,s2 = sum - sum1;
}
return;
}
DFS(sum1,i + 1);
DFS(sum1 + d[i],i + 1);
}
int main()
{
string s;
while(getline(cin,s))
{
if(!GetNum(s)) cout << "ERROR" << endl;
else
{
min_sum = INT32_MAX;
s1 = 0,s2 = 1;
DFS(0,0);
if(s1 > s2)
cout << s1 << " " << s2 << endl;
else
cout << s2 << " " << s1 << endl;
}
}
return 0;
} #include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
char str[10];
bool flag = false;
int total = 0;
vector<int> cnt;
vector<int> nums;
bool isDigit(char ch) {
return ch >= '0' && ch <= '9';
}
void solve() {
cnt.clear();
int n = nums.size();
int left = n >> 1;
int right = n - left;
int left_status_len = 1 << left;
int right_status_len = 1 << right;
int res = 0;
for (int status = 0; status < left_status_len; ++status) {
int temp = 0;
for (int l = 0; l < left; ++l) {
if ((status >> l) & 1) {
temp += nums[l];
}
}
if (temp <= total / 2) {
cnt.push_back(temp);
}
}
sort(cnt.begin(), cnt.end());
for (int status = 0; status < right_status_len; ++status) {
int temp = 0;
for (int r = 0; r < right; ++r) {
if ((status >> r) & 1) {
temp += nums[r + left];
}
}
int index = upper_bound(cnt.begin(), cnt.end(), total / 2 - temp)
- cnt.begin() - 1;
if (index >= 0){
res = max(res, temp + cnt[index]);
}
}
cout << total - res << ' ' << res << endl;
}
int main() {
while(scanf("%s",str) != EOF){
char ch;
scanf("%c",&ch);
int len = strlen(str);
int num = 0;
for(int i = 0;i < len;i++){
if(isDigit(str[i]))
num = num * 10 + str[i] - '0';
else{
flag = true;
break;
}
}
if(!flag){
total += num;
nums.push_back(num);
}
if(ch == '\n'){
if(flag){
printf("ERROR\n");
}else{
solve();
}
nums.clear();
total = 0;
flag = false;
}
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 10000;
int main() {
string str;
while(getline(cin, str)) {
bool flag = true; //记录是否全为数字
long long arr[MAXN] = {0};
int num = 0; //记录当前正在处理哪个数字
for(int i = 0; i < str.size(); ++i){
if(str[i] == ' ') {
num++;
} else {
if(str[i] < '0' || str[i] > '9') {
flag = false; //有非数字出现
} else {
arr[num] = arr[num] * 10 + str[i] - '0';
}
}
}
if(!flag) {
cout << "ERROR" << endl;
continue;
}
num++;
long long dp[num], total = 0, mid;
for(int i = 0; i < num; ++i) {
dp[i] = arr[i];
total += arr[i];
}
mid = total / 2;
for(int i = 1; i < num; ++i) {
for(int j = 0; j < i; ++j) {
dp[i] = abs(dp[j] + arr[i] - mid) < abs(dp[i] - mid) ? dp[j] + arr[i] : dp[i];
}
}
long long sum1 = dp[0], sum2;
for(int i = 1; i < num; ++i) {
sum1 = abs(dp[i] - mid) < abs(sum1 - mid) ? dp[i] : sum1;
}
sum2 = total - sum1;
if(sum1 < sum2) { //方便后续降序输出
swap(sum1, sum2);
}
cout << sum1 << " " << sum2 << endl;
}
return 0;
} //借鉴于:https://blog.csdn.net/hh1986170901/article/details/105000680
//方法就是DFS剪枝
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
int handle(string s,int a[]){
int count = 0;
int i = 0;
while(s[i] != '\n' && i < s.size()){
if(s[i] >= '0' && s[i] <= '9'){
while(s[i] >= '0' && s[i] <= '9'){
a[count] = a[count] * 10 + s[i] - '0';
i++;
if(i >= s.size()) break;
}
count++;
continue;
}else if(s[i] != ' ' && s[i] != '\n'){
return 0;
}
i++;
}
for(int i = 0;i < count;i++)
if(a[i] == 0)
return 0;
return count;
}
bool cmp(int a,int b){
return a > b;
}
int a[50000];
int ans;
int n;
int half;
void dfs(int i,int sum){
if(i >= n || sum + (n-i) * a[i] < ans)
return;
if(sum+a[i] <= half){
ans = max(ans,sum+a[i]);
dfs(i+1,sum+a[i]);
}
dfs(i+1,sum);
}
int main(){
string s;
while(getline(cin,s)){
memset(a,0,sizeof(a));
n = handle(s,a);
if(!n){
cout << "ERROR" << endl;
continue;
}
int sum = 0;
for(int i = 0;i < n;i++)
sum += a[i];
half = sum / 2;
sort(a,a+n,cmp);
ans = 0;
dfs(0,0);
cout << sum - ans << " " << ans << endl;
}
return 0;
} 1、值等于一半,可以退出
2、剩下的值全部选上也不能更新当前答案,可以退出(用前缀和)
3、若加上当前元素,大于一半,则不能加
#include <iostream>
#include <sstream>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 1000;
int q[N];
LL pre[N];
int idx;
bool f[N];
LL S,sum, res = 0;
void dfs(int u)
{
if(res == S/2) return ;
if(u == idx)
{
if(sum <= S / 2)
{
res = max(res,sum);
return ;
}
}
if(pre[idx] - pre[u] + sum <= res) return;
if((LL)q[u] + sum <= S / 2)
{
sum += q[u];
dfs(u + 1);
sum -= q[u];
}
dfs(u + 1);
}
int main()
{
string s;
while(getline(cin,s))
{
if(s.size() == 0) continue;
bool flag = false;
stringstream ss;
ss << s;
idx =0;
S = 0;
string str;
while(ss >> str)
{
LL a = 0;
for(int i = 0; i < str.size(); i ++ )
{
if(str[i] >= '0' && str[i] <= '9')
a = a * 10 + str[i] - '0';
else
{
flag = true;
break;
}
}
if(flag) break;
q[idx ++ ] = a;
pre[idx] = pre[idx - 1] + a;
S += a;
}
if(flag)
{
puts("ERROR");
continue;
}
//此时q中存储了数字,idx中存储了有多少个
res = 0;
sum = 0;
memset(f,false,sizeof f);
dfs(0);
S -= res;
if(res < S) swap(res,S);
printf("%lld %lld\n",res,S);
}
return 0;
}
#include <iostream>
#include <string>
#include <vector>
#include <limits.h>
#include <unordered_set>
#include <unordered_map>
void DFS(int i, int sum, int& max, const int c, const std::vector<int>& v){
if (i >= v.size()){
return;
}
if (sum > c){
return;
}
if (sum + v[i] == c){
max = std::max(max, sum + v[i]);
return;
}
if (sum + v[i] < c){
max = std::max(max, sum + v[i]);
DFS(i+1, sum + v[i], max, c, v);
}
if (max == c){
return;
}
DFS(i+1, sum, max, c, v);
}
int main(){
std::string line;
while(std::getline(std::cin, line)){
std::vector<int> v;
int start = 0;
bool error = false;
int sum = 0;
for (int i = 0; i < line.size(); i++){
if ((line[i]< '0' || line[i] > '9') && line[i]!= ' ' ){
error = true;
break;
}
if (line[i] == ' '){
int num = std::stoi(line.substr(start, i - start));
v.push_back(num);
sum += num;
start = i + 1;
}
}
if (error){
std::cout << "ERROR" << std::endl;
continue;
}
int num = std::stoi(line.substr(start));
v.push_back(num);
sum += num;
int c = sum / 2;
int max = 0;
DFS(0, 0, max, c, v);
std::cout << sum - max << " " << max << std::endl;
}
return 0;
} import sys
def DFS(num_array,result_half,num_index,tmp_sum):
if tmp_sum==result_half:
return tmp_sum
if num_index==len(num_array):
return tmp_sum
tmp_sum2=DFS(num_array,result_half,num_index+1,tmp_sum)
if (tmp_sum+num_array[num_index])<=result_half:
tmp_sum1=DFS(num_array,result_half,num_index+1,tmp_sum+num_array[num_index])
if tmp_sum1<tmp_sum2:
return tmp_sum2
else:
return tmp_sum1
else:
return tmp_sum2
def check_num(num_str):
for a in num_str:
if a not in '1234567890 \n':
return False
return True
while True:
num_str=sys.stdin.readline()
if not num_str:
break
if check_num(num_str)==False:
print('ERROR')
continue
num_array=list(map(int,num_str.split()))
result=DFS(num_array,sum(num_array)/2,0,0)
print(sum(num_array)-result,result)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX=25;
bool isGo; //是否继续
LL n, avg, ans, re[MAX];
void DFS(LL index, LL cnt){
if(isGo==false || index>=n){ //如果不加isGo判断,那么会超时
if(ans == avg) isGo = false;
return ;
}
if(abs(ans-avg) > abs(cnt-avg)) ans = cnt; //要每次都判断一下
DFS(index+1, cnt+re[index+1]); //选
DFS(index+1, cnt); //不选
}
int main(){
bool flag; //是否非法
LL i, t, sum;
string s;
while(getline(cin, s)){
s += ' ';
n = 0, t = 0, sum=0; //sum记录总数
flag = false;
for(i=0; i<s.size(); i++){
if(s[i] == ' '){
re[n++] = t;
sum += t;
t = 0;
}else{
if(s[i]<'0' || s[i]>'9'){
flag = true;
break;
}
t = t*10 + (s[i]-'0');
}
}
if(flag){
printf("ERROR\n");
continue;
}
avg = sum / 2;
ans = 0;
isGo = true;
DFS(-1, 0);
if(sum-ans > ans) printf("%lld %lld\n", sum-ans, ans);
else printf("%lld %lld\n", ans, sum-ans);
}
return 0;
} 这个题也是神了~之前在本地测试出现各种毛病,最后气得直接提交,然后过了。。。。后来回过头来仔细思考代码,发现isGo这个条件的设置竟然如此的重要。。。不知道是不是和测试数据有关的缘故,毕竟改变isGo的条件是找到了均值(即这个条件似乎太苛刻了)。
#include<iostream>
(720)#include<string>
#include<cmath>
using namespace std;
const int maxn=10010;
int sum,half_sum,near,bestsum;
int a[maxn];
void DFS(int index,int nowsum,int n){
if(index==n) return;
if(abs(nowsum-half_sum)<near){
near=abs(nowsum-half_sum);
bestsum=nowsum;
}
if(nowsum<half_sum){
DFS(index+1,nowsum+a[index],n);
}
DFS(index+1,nowsum,n);
}
int main(){
string s;
while(getline(cin,s)){
int len=s.size();
bool flag=true;
for(int i=0;i<len;i++){
if(!(((s[i]>='0' && s[i]<='9')) || (s[i]==' '))){
flag=false;
break;
}
}
if(flag==false) cout << "ERROR" << endl;
else{
int i=0,cnt=0,j=0;
sum=0;
while(i<len){
if(s[j]>='0' && s[j]<='9') j++;
else{
string temp=s.substr(i,j-i);
a[cnt]=stoi(temp);
sum+=a[cnt];
cnt++;
j=j+1;
i=j;
}
}
// cout << a[0] << a[1] << a[2] << a[3] << a[4];
half_sum=sum/2,near=1000000;
DFS(0,0,cnt);
int ans1=max(sum-bestsum,bestsum);
int ans2=sum-ans1;
cout << ans1 << " " << ans2 << endl;
}
}
return 0;
} #define max(x,y) ((x)>(y)?(x):(y))
#include <iostream>
#include <vector>
using namespace std;
vector<int> v;
int one, half;
void dfs(int index, int summed) {
if (index == v.size())
return;
int sum = v[index] + summed;
if (sum <= half) {
one = max(one, sum);
if (one == half)
return;
dfs(index + 1, sum);
}
dfs(index + 1, summed);
}
int main() {
int sum = 0, n;
while (true) {
cin >> n;
v.push_back(n);
sum += n;
char c = getchar();
if (c == '\n' || c == EOF) {
// deal with an empty case.
if (sum == 755827)
return 0;
// one problem input finished.
one = 0;
half = sum / 2;
dfs(0, 0);
cout << sum - one << ' ' << one << endl;
// next question.
v.clear();
sum = 0;
if (c == EOF)
break;
}
else if (c != ' ' && !isdigit(c)) {
// invalid input.
cout << "ERROR\n";
v.clear();
sum = 0;
while (getchar() != '\n');
cin.clear();
continue;
}
};
return 0;
}