您的位置:首页 > 其它

【codeforces 733D】【贪心 乱搞】D. Kostya the Sculptor【给你n个长方形,让你找出2个或1个长方体,使得他们拼接成的长方体的内接圆半径最大】

2016-11-01 17:16 525 查看
传送门: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
;
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
[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
;

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;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: