传送门:http://codeforces.com/contest/733/problem/D
题意:给你n个长方形,让你找出2个或1个长方体,使得他们拼接成的长方体的内接圆半径最大(两个矩形拼接的条件是他们有一个面完全相同)
思路:
很容易想到一个长方体的内接圆半径是由他的最短的那条边决定的,
拼的时候贪心思想就是拼完之后让最小边变大,所以按两条边较长那个面把两个长方体拼起来
纯暴力复杂度是O(n^2)
设长方体的边长从大到小分别为a,b,c,
我们读入的时候将长方体边长排序
然后sort 以a为第一关键字 以b为第二关键字 以c为第三关键字
然后再进行拼接操作复杂度是O(n)
代码:
#include <bits/stdc++.h>
using namespace std;
#define ff first
#define ss second
#define rep(i,k,n) for(int i=k;i<=n;i++)
typedef pair<pair<int, int>, pair<int, int> >piii;
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
const int N=1e5+10;
piii p[N];
int n, a[3];
int main(){
read(n);
int ans = 0,pos1, pos2 = -1;
rep(i, 1, n){
rep(j, 0, 2)read(a[j]);
sort(a, a + 3);
p[i] = {{a[1], a[2]}, {a[0], i}};
if(ans < a[0])ans = a[0], pos1 = i;//不合并
}
sort(p + 1, p + n + 1);
rep(i, 1, n){
if(p[i].ff == p[i + 1].ff){//按较大的两条边合并
int x = p[i].ss.ff + p[i + 1].ss.ff;
x = min(x, p[i].ff.ff);
if(ans < x) ans = x, pos1 = p[i].ss.ss, pos2 = p[i + 1].ss.ss;
}
}
if(pos2 == -1){
printf("1\n%d\n", pos1);
}
else{
printf("2\n%d %d\n", pos1, pos2);
}
return 0;
}
PS:巧用pair比手写结构体方便一些
当然当a,b相等时也可以用map找到c最大的两个三元组来更新答案,这样复杂度为O(nlogn)
代码:
(结构体写的,写的有些啰嗦)
#include <bits/stdc++.h>
using namespace std;
#define rep(i,k,n) for(int i=k;i<=n;i++)
typedef pair<int, int> P;
const int N=1e5+10;
int a[N][3];
std::map<P, int> mp;
int n;
struct node
{
int a[3];
int pos;
void st(){
sort(a, a+3);
}
bool operator < (const node& tmp)const{
if(tmp.a[1]==a[1]){
if(tmp.a[2]==a[2]){
return a[0]<tmp.a[0];
}
else return a[2]<tmp.a[2];
}
else return a[1]<tmp.a[1];
}
}p[N];
int main(){
cin>>n;
rep(i, 1, n){
cin>>p[i].a[0]>>p[i].a[1]>>p[i].a[2];
p[i].pos = i;
p[i].st();
}
sort(p+1, p+n+1);
/* rep(i, 1, n){//输出
cout<<p[i].a[0]<<p[i].a[1]<<p[i].a[2]<<endl;
}*/
int mx=0, pos1;
rep(i, 1, n){//不合并
if(p[i].a[0]>mx)pos1=p[i].pos, mx = p[i].a[0];
}
rep(i, 1, n){//添加二元组
mp[make_pair(p[i].a[1], p[i].a[2])]++;
}
int pos21, pos22,i=1;
bool flag=false;
while(i<=n){//合并后
int sz=mp[make_pair(p[i].a[1], p[i].a[2])];
if(sz <=1)i++;
else{
i += sz;
int fg = min(p[i-1].a[1], p[i-2].a[0]+p[i-1].a[0]);
if(fg > mx){
flag=true;
mx=fg;
pos21=p[i-2].pos;
pos22=p[i-1].pos;
}
}
}
if(!flag){
puts("1");
printf("%d\n", pos1);
}
else{
puts("2");
printf("%d %d\n", pos21, pos22);
}
return 0;
}