L - Basketball Gym - 100741L---e二进制枚举
2017-08-23 14:09
288 查看
题意:
输入n,m。分别代表每个队人数,然后下面两行,第一行n个数,每个数字代表每个人能力值,第二行m个数,每个数字代表每个人能力值。求从n中选几个人,m中选几个人,能力值之和相等(即:两队势力平衡)的方法有多少种,注意:两队所选的人多数可以不同,只要能量值和相能就可以。
思路:
二进制枚举,把每种情况列举出来,然后看两个队和相等的情况有多少种,方法就有多少种。
第一遍的代码(超时): 将两个组的所有自己子集情况分别存到两个数组里。然后比照和相等的情况,然而超时了。
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std;
int ans; int k=0,l=0;
int N[18],M[18];
int aa[18],bb[18];
void subset(int n,int s,int chose,int *a)
{
long long int tmp=0;
for(int i=0;i<n;i++)
{
if(s&(1<<i))//如果两个位置上都是1则为真
// printf("%d ",i);
tmp+=a[i];
}
if(chose==1)
{
if(tmp)
aa[k++]=tmp;
}
if(chose==0)
{
if(tmp)
bb[l++] =tmp;
}
}
void solve(int n,int m)
{
for(int i=0;i<(1<<n);i++)
{
subset(n,i,1,N);
}
for(int i=0;i<(1<<m);i++)
{
subset(m,i,0,M);
}
for(int i=0;i<k;i++)
for(int j=0;j<l;j++)
{
if(aa[i]==bb[j])
ans++;
}
cout<<ans<<endl;
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
cin>>N[i];
for(int j=0;j<m;j++)
cin>>M[j];
solve(n,m);
}
AC 代码:(解决超时的问题)(应用map)
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std;
int k=0,l=0;
int N[18],M[18];
//int aa[18],bb[18];
map<long long,int> sa,sb;
map<long long,int> ::iterator it ;
void subset(int n,int s,int chose,int *a)// s 表示 2^n 种情况中的一种
{
long long int tmp=0;
for(int i=0;i<n;i++)
{
if(s&(1<<i))//如果两个位置上都是1则为真
// printf("%d ",i);
tmp+=a[i];
}
if(chose==1)
{
if(tmp)
{
if(sa.count(tmp))
sa[tmp]++;
else
sa.insert(make_pair(tmp,1));
}
// aa[k++]=tmp;
}
if(chose==0)
{
if(tmp)
{
if(sb.count(tmp))
sb[tmp]++;
else
sb.insert(make_pair(tmp,1));
}
// bb[l++] =tmp;
}
}
void solve(int n,int m)
{
long long int ans=0;
for(int i=0;i<(1<<n);i++)
{
subset(n,i,1,N);
}
for(int i=0;i<(1<<m);i++)
{
subset(m,i,0,M);
}
// for(int i=0;i<k;i++)
// for(int j=0;j<l;j++)
// {
// if(aa[i]==bb[j])
// ans++;
//
// }
for ( it=sa.begin();it!=sa.end();it++)
{
if(sb.count(it->first))
{
ans+=((it->second) * sb[it->first]);
}
}
printf("%lld\n",ans);
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&N[i]);
for(int j=0;j<m;j++)
scanf("%d",&M[j]);
solve(n,m);
}
输入n,m。分别代表每个队人数,然后下面两行,第一行n个数,每个数字代表每个人能力值,第二行m个数,每个数字代表每个人能力值。求从n中选几个人,m中选几个人,能力值之和相等(即:两队势力平衡)的方法有多少种,注意:两队所选的人多数可以不同,只要能量值和相能就可以。
思路:
二进制枚举,把每种情况列举出来,然后看两个队和相等的情况有多少种,方法就有多少种。
第一遍的代码(超时): 将两个组的所有自己子集情况分别存到两个数组里。然后比照和相等的情况,然而超时了。
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std;
int ans; int k=0,l=0;
int N[18],M[18];
int aa[18],bb[18];
void subset(int n,int s,int chose,int *a)
{
long long int tmp=0;
for(int i=0;i<n;i++)
{
if(s&(1<<i))//如果两个位置上都是1则为真
// printf("%d ",i);
tmp+=a[i];
}
if(chose==1)
{
if(tmp)
aa[k++]=tmp;
}
if(chose==0)
{
if(tmp)
bb[l++] =tmp;
}
}
void solve(int n,int m)
{
for(int i=0;i<(1<<n);i++)
{
subset(n,i,1,N);
}
for(int i=0;i<(1<<m);i++)
{
subset(m,i,0,M);
}
for(int i=0;i<k;i++)
for(int j=0;j<l;j++)
{
if(aa[i]==bb[j])
ans++;
}
cout<<ans<<endl;
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
cin>>N[i];
for(int j=0;j<m;j++)
cin>>M[j];
solve(n,m);
}
AC 代码:(解决超时的问题)(应用map)
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std;
int k=0,l=0;
int N[18],M[18];
//int aa[18],bb[18];
map<long long,int> sa,sb;
map<long long,int> ::iterator it ;
void subset(int n,int s,int chose,int *a)// s 表示 2^n 种情况中的一种
{
long long int tmp=0;
for(int i=0;i<n;i++)
{
if(s&(1<<i))//如果两个位置上都是1则为真
// printf("%d ",i);
tmp+=a[i];
}
if(chose==1)
{
if(tmp)
{
if(sa.count(tmp))
sa[tmp]++;
else
sa.insert(make_pair(tmp,1));
}
// aa[k++]=tmp;
}
if(chose==0)
{
if(tmp)
{
if(sb.count(tmp))
sb[tmp]++;
else
sb.insert(make_pair(tmp,1));
}
// bb[l++] =tmp;
}
}
void solve(int n,int m)
{
long long int ans=0;
for(int i=0;i<(1<<n);i++)
{
subset(n,i,1,N);
}
for(int i=0;i<(1<<m);i++)
{
subset(m,i,0,M);
}
// for(int i=0;i<k;i++)
// for(int j=0;j<l;j++)
// {
// if(aa[i]==bb[j])
// ans++;
//
// }
for ( it=sa.begin();it!=sa.end();it++)
{
if(sb.count(it->first))
{
ans+=((it->second) * sb[it->first]);
}
}
printf("%lld\n",ans);
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&N[i]);
for(int j=0;j<m;j++)
scanf("%d",&M[j]);
solve(n,m);
}
相关文章推荐
- Basketball Gym - 100741L 二进制枚举子集
- 二进制枚举子集与容斥
- UVALive 6918 And Or 数学二进制+枚举
- 二进制序列化和枚举需要注意!!!!!
- uva 10325 The Lottery (容斥原理)dfs枚举 或二进制枚举
- c# 二进制或算法实现枚举的HasFlag函数
- 技巧-二进制枚举
- C++之暴力算法突破-二进制枚举子集
- poj 1416 Shredding Company 二进制枚举
- Water Gate Management(二进制枚举组合排列模板 n个数的子集)
- 【UVA】11464-Even Parity(二进制枚举子集)
- Poj(2784),二进制枚举最小生成树
- POJ 1753 Flip Game(二进制枚举)
- HDU 4810 Wall Painting【二进制+异或+暴力枚举】
- codeforces-#476B. Dreamoon and WiFi(dfs、二进制枚举)
- Codeforces 875D High Cry [枚举+二进制]
- POJ 2784 Buy or Build(二进制枚举 + 最小生成树)
- Atcoder 045 -二进制枚举
- UVA1511 Buy or Build 二进制枚举+最小生成树kruskal
- 凑成整数x----二进制枚举