Perket
#include<bits/stdc++.h>
using namespace std;
int n;
int r[100000]={0};
int vis[100000]={0};
int x[20]={0};
int y[20]={0};
int sum=100000000;
void dfs(int cur){
if(cur<=n&&cur){//边界
int l1=1,l2=0;
for(int i=0;i<cur;i++){
l1*=x[r[i]];
l2+=y[r[i]];
}
l1=abs(l1-l2);
sum=min(sum,l1);
}
if(cur>=n+1)return;//剪纸
int s=cur?r[cur-1]+1:1;//增量构造法
for(int i=s;i<=n;i++){
r[cur]=i;//枚举子集就不用回溯了
dfs(cur+1);
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
dfs(0);//注意要从0开始放元素
cout<<sum;
}
2自然数拆分
#include<bits/stdc++.h>
using namespace std;
int a[100000]={0};
int n;
void dfs(int cur,int sum,int ans){
if(sum==n){
cout<<a[0];
for(int i=1;i<cur;i++){
cout<<"+";
cout<<a[i];
}
cout<<endl;
return;
}
if(sum>n)return;
for(int i=ans;i<n;i++){
a[cur]=i;
dfs(cur+1,sum+i,i);
}
}
int main(){
cin>>n;
dfs(0,0,1);
}
Perket用类似于自然数拆分的写法:
#include<bits/stdc++.h>
using namespace std;
int n;
int r[100000]={0};
int vis[100000]={0};
int x[20]={0};
int y[20]={0};
int sum=100000000;
void dfs(int cur,int ans){
if(cur<=n&&cur){
int l1=1,l2=0;
for(int i=0;i<cur;i++){
l1*=x[r[i]];
l2+=y[r[i]];
}
l1=abs(l1-l2);
sum=min(sum,l1);
}
if(cur>=n+1)return;
for(int i=ans+1;i<=n;i++){
r[cur]=i;
dfs(cur+1,i);
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>x[i]>>y[i];
dfs(0,0);//注意要从0开始放元素
cout<<sum;
}