中途相遇法

来源:互联网 发布:医学继续教育网络 编辑:程序博客网 时间:2024/05/06 22:08

FZU  2178】礼物分配(经典题)

<span style="font-size:14px;"><span style="font-size:14px;">#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <string>#include <vector>#include <math.h>using namespace std;int v[35],w[35];vector<int>vec[40];int main() {int n,t;scanf("%d",&t);while(t--){scanf("%d",&n);for(int i=0;i<n;i++) scanf("%d",&v[i]);for(int i=0;i<n;i++) scanf("%d",&w[i]);for(int i=0;i<=n;i++) vec[i].clear();int half=n/2;for(int i=0;i<(1<<half);i++){int cnt=0,sum1=0,sum2=0;for(int j=0;j<half;j++){if(i&(1<<j)){sum1+=v[j];cnt++;}else{sum2+=w[j];}}vec[cnt].push_back(sum1-sum2);}for(int i=0;i<=half;i++) {sort(vec[i].begin(),vec[i].end());vec[i].erase(unique(vec[i].begin(),vec[i].end()),vec[i].end());}int ans=0x3f3f3f3f;for(int i=0;i<(1<<(n-half));i++){int cnt=0,sum1=0,sum2=0;for(int j=0;j<(n-half);j++){if(i&(1<<j)){sum1+=v[j+half];cnt++;}else{sum2+=w[j+half];}}vector<int>::iterator iter; int p=n-half-cnt,sum=sum1-sum2;iter=lower_bound(vec[p].begin(),vec[p].end(),-sum);if(iter!=vec[p].end() && abs(*iter+sum)<ans){ans=abs(*iter+sum);}     if(iter!=vec[p].begin()){--iter;if(ans>abs(*iter+sum)) ans=abs(*iter+sum);}}printf("%d\n",ans);}return 0;}</span></span>

【UVALive 2965】 Jurassic Remains  (即UVA 1326、POJ 1903)

大白书P57  例题25

<span style="font-size:14px;"><span style="font-size:14px;">#include <bits/stdc++.h>using namespace std;map<int,int>table;int a[30];char s[1000];int bitcount(int x){return x == 0 ? 0 : bitcount(x/2) + (x&1);}int main(){int n;while(~scanf("%d",&n) && n){memset(a,0,sizeof(a));for(int i=0;i<n;i++){scanf("%s",s);for(int j = 0; s[j] != '\0'; j++){a[i] ^= (1 << (s[j]-'A'));}}table.clear();int n1=n/2,n2=n-n1;for(int i = 0 ; i < (1 << n1) ; i++){int x = 0;for(int j = 0 ; j < n1 ; j++){if(i & (1 << j)){x ^= a[j];}}map<int, int>::iterator fi=table.find(x);if(fi==table.end() || bitcount(table[x]) < bitcount(i)) table[x] = i;}int ans=0;for(int i = 0; i < (1<<n2); i++){int x=0;for(int j = 0; j < n2; j++){if(i & (1 << j)) {x ^= a[n1+j];}}map<int, int>::iterator fi=table.find(x);if(fi!=table.end() && bitcount(ans) < bitcount(table[x]) + bitcount(i)){ans = (i << n1) ^ table[x];}}printf("%d\n",bitcount(ans));for(int i = 0; i < n; i++){if(ans & (1 << i)){printf("%d ",i+1);}}printf("\n");}return 0;} </span></span>

【POJ 3977】Subset

找出和的绝对值最小的子集,输出和,以及子集个数

<span style="font-size:14px;">#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <string>#include <map>using namespace std;#define ll __int64map<ll, int>table;ll a[40];ll ll_abs(ll x){return x<0 ? -x : x;}int main(){int n;while(~scanf("%d", &n) && n){for(int i = 0; i < n; i++){scanf("%I64d", &a[i]);}int n1 = n/2, n2 = n-n1;table.clear();pair<ll, int>result(ll_abs(a[0]), 1); //存最小的 for(int i = 0; i < (1<<n1); i++){ll ans = 0;int ni = 0;for(int j = 0; j < n1; j++){if(i & (1<<j)){ans += a[j];ni++;}}if(ni == 0) continue;result = min(result, make_pair(ll_abs(ans), ni));//pair中先比较first的位置,在比较second的位置上的值 if(!table.count(ans) || table[ans] > ni) table[ans]=ni;}ll sum = 0x7FFFFFFF;int num = 100;for(int i = 0; i < (1<<n2); i++){ll ans = 0;int ni = 0;for(int j = 0; j < n2; j++){if(i & (1<<j)){ans += a[n1+j];ni++;}}if(ni == 0) continue;result = min(result, make_pair(ll_abs(ans), ni));map<ll , int>:: iterator fi = table.lower_bound(-ans);int s1, s2;if(fi != table.end()) {result = min(result, make_pair(ll_abs(fi->first+ans), ni+fi->second));}if(fi != table.begin()){--fi;result = min(result, make_pair(ll_abs(fi->first+ans), ni+fi->second));}}printf("%I64d %d\n",result.first,result.second);}return 0;}</span>

0 0
原创粉丝点击