poj之旅——3977

来源:互联网 发布:淘宝网logo图片 编辑:程序博客网 时间:2024/06/14 19:30

题目描述:给出n个数,求一个非空子集绝对值尽量小。

题解:非常明显的折半枚举。必须用map做,我原来用数组和vector,结果TLE了。。。

       逼着我用奇怪的迭代器。


参考程序:

#include<cstdio>#include<algorithm>#include<map>#include<limits>#include<iostream>#define maxn 500using namespace std;typedef long long LL;LL Abs(const LL& x){return x>=0?x:-x;}LL a[maxn];int n;int main(){while (cin>>n && n){map<LL,int>b;for (int i=0;i<n;i++)cin>>a[i];pair<LL,int>result(Abs(a[0]),1);int half=n/2;for (int i=1;i<1<<half;i++){LL sum=0;int ct=0;for (int j=0;j<half;j++)if (i>>j &1){sum+=a[j];ct++;}result=min(result,make_pair(Abs(sum),ct));map<LL,int>::iterator it=b.find(sum);if (it != b.end())it->second=min(it->second,ct);else b[sum]=ct;}for (int i=1;i<1<<(n-half);i++){LL sum=0;int ct=0;for (int j=0;j<n-half;j++)if (i>>j &1){sum+=a[half+j];ct++;}result=min(result,make_pair(Abs(sum),ct));map<LL,int>::iterator it=b.lower_bound(-sum);if (it!=b.end())result=min(result,make_pair(Abs(it->first+sum),it->second+ct));if (it!=b.begin()){it--;result=min(result,make_pair(Abs(it->first+sum),it->second+ct));}}cout<<Abs(result.first)<<" "<<result.second<<endl;}return 0;}

给出vector和array的,留作纪念:

vector:

#include<cstdio>#include<algorithm>#include<map>#include<vector>#define maxn 50using namespace std;typedef long long LL;LL Abs(const LL& x){return x>=0?x:-x;}LL a[maxn];vector<LL> c;int n;void Min(LL &res,int &ans,LL sum,int ct){if (sum>res)return;if (res>sum){res=sum;ans=ct;return;}else ans=min(ans,ct);}int main(){while (scanf("%d",&n)==1 && n){map<LL,int>b;for (int i=0;i<n;i++)scanf("%lld",&a[i]);LL res=a[0];int ans=1;int half=n/2;for (int i=1;i<1<<half;i++){LL sum=0;int ct=0;for (int j=0;j<half;j++)if (i>>j &1){sum+=a[j];ct++;}Min(res,ans,Abs(sum),ct);c.push_back(sum);b[sum]=min(b[sum],ct);}sort(c.begin(),c.end());for (int i=1;i<1<<(n-half);i++){LL sum=0;int ct=0;for (int j=0;j<n-half;j++)if (i>>j &1){sum+=a[half+j];ct++;}Min(res,ans,Abs(sum),ct);int loc=lower_bound(c.begin(),c.end(),-sum)-c.begin();if (loc!=c.size())Min(res,ans,Abs(c[loc]+sum),b[c[loc]]+ct);if (loc!=0)Min(res,ans,Abs(c[loc-1]+sum),b[c[loc-1]]+ct);}printf("%lld %d\n",Abs(res),ans);}return 0;}

array:

#include<cstdio>#include<algorithm>#include<map>#include<vector>#define maxn 50#define expn 1<<20using namespace std;typedef long long LL;LL Abs(const LL& x){return x>=0?x:-x;}LL a[maxn];LL c[expn];int n;void Min(LL &res,int &ans,LL sum,int ct){if (sum>res)return;if (res>sum){res=sum;ans=ct;return;}else ans=min(ans,ct);}int main(){while (scanf("%d",&n)==1 && n){map<LL,int>b;for (int i=0;i<n;i++)scanf("%lld",&a[i]);LL res=a[0];int ans=1;int half=n/2;int cnt=0;for (int i=1;i<1<<half;i++){LL sum=0;int ct=0;for (int j=0;j<half;j++)if (i>>j &1){sum+=a[j];ct++;}Min(res,ans,Abs(sum),ct);c[cnt++]=sum;b[sum]=min(b[sum],ct);}sort(c,c+cnt);for (int i=1;i<1<<(n-half);i++){LL sum=0;int ct=0;for (int j=0;j<n-half;j++)if (i>>j &1){sum+=a[half+j];ct++;}Min(res,ans,Abs(sum),ct);int loc=lower_bound(c,c+cnt,-sum)-c;Min(res,ans,Abs(c[loc]+sum),b[c[loc]]+ct);if (loc!=0)Min(res,ans,Abs(c[loc-1]+sum),b[c[loc-1]]+ct);}printf("%lld %d\n",Abs(res),ans);}return 0;}

//坑爹的poj,调了2个小时。。。。

0 0
原创粉丝点击