【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 __int64
map<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>