19070 音响外放
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定
Description
贝壳找房2021届校招算法卷
本题目难度略高于前面题目
牛牛寝室有四人,他们打算用一个音响播放自己喜欢的曲子。
但是四人的喜好各不相同,他们每个人选取了自己最喜欢的n首曲子。
也就是一共有4n首曲子,第i首的长度为ai 。
但是他们不能容忍播放别人的曲子的时间比他们长很多,牛牛可以从这些曲子中删掉一些,使得每个人的播放总长大致相等。
牛牛想知道在每个人都至少都播放1首歌的情况下,播放最长时间和播放最短时间的差距最小是多少。
输入格式
第一行输入一个整数n,表示每个人都选择了n首曲子。
随后4行,每行n个整数,分别表示第每名室友喜欢的歌曲的时间长度。
1≤n≤10,100≤ai≤600
输出格式
输出一个整数,表示播放最长时间和播放最短时间的最小差距。
输入样例
3
240 300 360
600 200 200
300 400 500
600 600 600
输出样例
100
提示
分别选用{1,3},{1},{3},{1}时,差距为100。 题目解析:看题目先看数据。n范围比较小,所以可以用DFS(递归实现指数型枚举)
得到每一个人所有的可能时间,总数最大不超过1024,用数组分别存储4个人的所有可能时间。 然后枚举…
如何枚举呢?我们可以先假设第1个人选择的曲子长度X一定是所有人里面最小时间(X最多1024种可能),
那么其他人一定比第1个人的值大,找到其他三个人比X大的最小值,求出差。
然后我们又假设第2个人选择的曲子长度Y一定是所有人里面最小的,参照第一个人处理方法,再来一次。
然后我们又假设第3个人选择的曲子长度Z一定是所有人里面最小的,再来一套处理。
然后我们又假设第4个人选择的曲子长度V一定是所有人里面最小的,再来一套处理。
答案是个极值,在上述枚举过程中必然可以找到。复杂度为O(2^n)。
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int a[4][11];
int len[4][1050];
int n;
int p;
void dfs(int i,int depth,int sum)
{
//终止条件
if(depth==n)
{
len[i][p++]=sum;
return;
}
//不取和取
dfs(i,depth+1,sum);
sum=sum+a[i][depth];
dfs(i,depth+1,sum);
sum=sum-a[i][depth];
}
int getDifference(int i,int x)
{
int maxm;//其余三个人的最小值中的最大值
int p=0;
int minm[3];//局部最小
for(int j=0;j<4;j++)
{
if(j==i)continue;
else
{
minm[p]=10000;
for(int k=1;k<pow(2,n);k++)
{
if(len[j][k]>=x)
{
minm[p]=min(minm[p],len[j][k]);
}
}
p++;
}
}
maxm=minm[0];
for(int j=0;j<3;j++)
{
maxm=max(maxm,minm[j]);
}
// if(i==0)
// {
// cout<<"minm[2]:"<<minm[2]<<endl;
// }
return maxm-x;
}
int main()
{
cin>>n;
for(int i=0;i<4;i++)
for(int j=0;j<n;j++)
cin>>a[i][j];
for(int i=0;i<4;i++)
{
p=0;
dfs(i,0,0);
}
// for(int i=0;i<4;i++)
// {
// for(int j=0;j<pow(2,n);j++)
// {
// cout<<len[i][j]<<" ";
// }
// cout<<endl;
// }
//轮流假设四个人其中之一是最小值
int minm=10000;
for(int i=0;i<4;i++)
{
int j;
for( j=1;j<pow(2,n);j++)
{
minm=min(minm,getDifference(i,len[i][j]));
// cout<<getDifference(i,len[i][j])<<endl;
}
}
cout<<minm<<endl;
// cout<<getDifference(2,len[2][1]);
return 0;
}
2293

被折叠的 条评论
为什么被折叠?



