vijos p1693——Miku_Nobody

背景

听完了美妙的葱歌版<两个人的焰火>,F慢慢从石化中恢复了回来(= =!你以为是溪风和水碧啊).复原后的F悲哀地发现已经早晨了,他要去上学了.......
......放学后
F(回到家):= =||||||无数黑线
葱歌:What happened,怎么这么囧啊?
F:我们学校......搞唱歌比赛...= =一个MM(算不算呢?其实MM是无所谓有,无所谓无的......)唱了一首很多年前的老歌...实在太老了...老得我囧.现在脑子里全是这歌.
葱歌:是不是Nobody啊?我也会唱哦~~
F(黑线++):不要啊~

描述

众所周知的(什么?你不知道?去百度一下),Nobody的团舞里有一个经典动作(那是相当的经典,经典了好几年),而这个动作是对称做两遍的.葱歌很喜欢这个动作(Mikuer们不要BS我...),她很想多做这个动作.
但是邪恶的F,为了少看这无语的动作,给了葱歌两排非负整数.一排A数,一排B数.A数有n个,B数有m个.如果一个A数和一个B数的二进制表示法中,每一位都不一样的话(不足的数高位补0),则A和B能够组成一个"对称音".每个数只能属于一个"对称音".葱歌想要最多的对称音,让她可以尽量多跳那个动作.

格式

输入格式

输入共3行.
第1行两个正整数n,m,表示A数n个,B数m个.
第2行n个非负整数,表示n个A数.
第3行m个非负整数,表示m个B数.

输出格式

一行一个正整数,表示最多能得到的"对称音"个数.如果一个对称音都得不到,输出"I want nobody nobody but you".

样例1

样例输入1

2 1
0 1
2

样例输出1

1

限制

1s

提示

数据范围
对于10%的数据,1<=n<=10,1<=m<=10.
对于100%的数据,1<=n<=200,1<=m<=200.

 

二分匹配,将A和B所有连接的情况都算出来,然后进行匈牙利算法,找匹配边。O(n³)不会超时。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=205;
 6 int vis[maxn],match[maxn];
 7 int map[maxn][maxn];
 8 int a[maxn],b[maxn];
 9 int n,m;int count;
10 inline bool dfs(int x)
11 {
12     for(int i=1;i<=m;i++)
13     {
14         if(vis[i]==false&&map[x][i])
15         {
16             vis[i]=true;
17             if(match[i]==-1||dfs(match[i]))
18             {
19                 match[i]=x;
20                 return true;
21             }
22         }
23     }
24     return false;
25 }
26 inline void hungary()
27 {
28     count=0;
29     memset(match,-1,sizeof(match));
30     for(int i=1;i<=n;i++)
31     {
32         memset(vis,false,sizeof(vis));
33         if(dfs(i))count++;
34     }
35     return ;
36 }
37 inline bool pd(int x,int y)
38 {
39     int p1[2000],p2[2000];
40     int temp1=0,temp2=0;
41     memset(p1,0,sizeof(p1));
42     memset(p2,0,sizeof(p2));
43     while(x!=0)
44     {
45         p1[++temp1]=(x&1);
46         x>>=1;
47     }
48     while(y!=0)
49     {
50         p2[++temp2]=(y&1);
51         y>>=1;
52     }
53     if(temp1<temp2)
54     {
55         for(int i=1;i<=temp1;i++)
56         if(p1[i]==p2[i])return false;
57         for(int i=temp1+1;i<=temp2;i++)
58         if(p2[i]==0)return false;
59         return true;
60     }
61     else
62     {
63         for(int i=1;i<=temp2;i++)
64         if(p1[i]==p2[i])return false;
65         for(int i=temp2+1;i<=temp1;i++)
66         if(p1[i]==0)return false;
67         return true;
68     }
69 }
70 inline void gg()
71 {
72     scanf("%d%d",&n,&m);
73     for(int i=1;i<=n;i++)
74     scanf("%d",&a[i]);
75     for(int i=1;i<=m;i++)
76     scanf("%d",&b[i]);
77     for(int i=1;i<=n;i++)
78     for(int j=1;j<=m;j++)
79     if(pd(a[i],b[j]))map[i][j]=true;
80     return ;
81 }
82 inline void print()
83 {
84     if(count==0)
85     printf("I want nobody nobody but you");
86     else printf("%d\n",count);
87     return ;
88 }
89 int main()
90 {
91     gg();
92     hungary();
93     print();
94     return 0;
95 }
View Code

 

 

 

转载于:https://www.cnblogs.com/937337156Zhang/p/6047235.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值