codeforces-922E-Careful Maneuvering
传送门:https://codeforces.com/contest/994/problem/E
题意:敌方的战斗机分为两组,其中一组 x 坐标为 -100,y 坐标各不相同。另一组 x坐标为 100 , y 坐标各不相同。我方的战斗机始终保持在x 坐标为 0 的位置。敌方的所有战斗机会发射两束激光,分别射向我方的两架战斗机,我方的战斗机都能灵敏避开,而激光继续传播,还可以将敌方战斗机击落。问我方战斗机分别应该待在哪里,好让激光射落的敌方战斗机最多。而现在你只要输出这个最大值。
我们发现这两组的横坐标是关于y轴对称的,所以只考虑纵坐标就好了,如果我方战斗机在y=k的位置,那么设第一组y=a,第二组y=b,所有k=(a+b)/2的战斗机都会被对方击落,为了避免小数,计算的时候不用除以2,数组开大一倍就行,不影响答案
一看n,m都不大于60,暴力应该可以做,但不能直接把他加起来,因为两架敌方飞机可能会打中同一架飞机,考虑用set去重
我们可以用两个set存每一个我方战斗机所在的位置对应的敌方可以击落战斗机的”位置“(存下标,可能有两架飞机在同一位置set会给你去重),顺便用map离散还能记下我方有多少个可能的位置,方便后面计算,然后他不是说我方有两台战斗机吗,那就两两合并,取两边能被消灭的最大值
貌似正解是……bitset ??
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[109],b[109]; 4 set<int>l[20009],r[20009],ll,rr; 5 map<int,int>mp; 6 int main() 7 { 8 int n,m; 9 scanf("%d%d",&n,&m); 10 for(int i=1; i<=n; i++) scanf("%d",&a[i]); 11 for(int j=1; j<=m; j++) scanf("%d",&b[j]); 12 int cnt=0;///我方有多少个可能的位置 13 for(int i=1; i<=n; i++) 14 { 15 for(int j=1; j<=m; j++) 16 { 17 if(mp[a[i]+b[j]]) 18 { 19 l[mp[a[i]+b[j]]].insert(i); 20 r[mp[a[i]+b[j]]].insert(j); 21 } 22 else 23 { 24 cnt++; 25 mp[a[i]+b[j]]=cnt; 26 l[cnt].insert(i); 27 r[cnt].insert(j); 28 } 29 } 30 } 31 set<int>::iterator it; 32 int ans=0; 33 for(int i=1; i<=cnt; i++)///两两合并 34 { 35 for(int j=i+1; j<=cnt; j++) 36 { 37 ll.clear(),rr.clear(); 38 for(it=l[i].begin(); it!=l[i].end(); it++) ll.insert(*it); 39 for(it=l[j].begin(); it!=l[j].end(); it++) ll.insert(*it); 40 for(it=r[i].begin(); it!=r[i].end(); it++) rr.insert(*it); 41 for(it=r[j].begin(); it!=r[j].end(); it++) rr.insert(*it); 42 ans=max(ans,(int)(rr.size()+ll.size()));///要强制转换为int 43 } 44 } 45 if(cnt==1) ans=l[1].size()+r[1].size(); 46 printf("%d ",ans); 47 return 0; 48 }