最优合并问题
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
给定k 个排好序的序列s1 , s2,……, sk , 用2 路合并算法将这k 个序列合并成一个序列。假设所采用的2 路合并算法合并2 个长度分别为m和n的序列需要m + n -1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。
为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。
对于给定的k个待合并序列,计算最多比较次数和最少比较次数合并方案。
Input
输入数据的第一行有1 个正整数k(k≤1000),表示有k个待合并序列。接下来的1 行中,有k个正整数,表示k个待合并序列的长度。
Output
输出两个整数,中间用空格隔开,表示计算出的最多比较次数和最少比较次数。
Sample Input
4
5 12 11 2
Sample Output
78 52
这个题的主要思路就是排序、求和、排序、求和......
只不过不要忘记加上每一次求和的结果。
例求最小的时候,其实2+5 被加了多次。
min :2 5 11 12
(2 + 5 - 1) + ((2 + 5) + 11 - 1) + (12 + ((2 + 5) + 11) - 1) = 52
max : 12 11 5 2
(12 + 11 - 1) + ((12 + 11) + 5 - 1) + (2 + ((12 + 11) + 5) - 1) = 78
#include<bits/stdc++.h>
using namespace std;
int a[1001], b[1010];
int n, m;
bool cmp(int x, int y)
{
return x > y;
}
int getmax(int *s)
{
int n = m;
int sum = 0;
while(n > 1)
{
sort(s, s + n, cmp);
s[0] = s[0] + s[1];
sum += s[0] - 1;
n--;
for(int i = 1; i < n; i++)
s[i] = s[i + 1];
}
return sum;
}
int getmin(int *s)
{
int n = m;
int sum = 0;
while(n > 1)
{
sort(s, s + n);
s[0] = s[0] + s[1];
sum += s[0] - 1;
n--;
for(int i = 1; i < n; i++)
s[i] = s[i + 1];
}
return sum;
}
int main()
{
cin>>m;
for(int i = 0; i < m; i++)
{
cin>>a[i];
b[i] = a[i];
}
cout<<getmax(a)<<" "<<getmin(b)<<endl;
return 0;
}
感觉上面的两个求最大最小可以合并,但是无论怎么改都不能AC,样例啥的都也过了,不知道哪里出错。下面就是自己改的,
终于知道哪里出错了, 每一次计算完一次都要重新排序,所以下面的代码是错误的,结果对只是巧合吧
#include<bits/stdc++.h>
using namespace std;
int n, m;
int a[1010], s[1010];
bool cmp(int x, int y)
{
return x > y;
}
int display(int *a)
{
int sum = 0, num = n;
while(num > 1)
{
a[0] = a[0] + a[1];
sum += a[0] - 1;
num--;
for(int i = 1; i < num; i++)
a[i] = a[i + 1];
}
return sum;
}
int main()
{
cin>>n;
for(int i = 0; i < n; i++)
{
cin>>a[i];
s[i] = a[i];
}
sort(s, s + n);///排序要在每一次最开始进行一次
sort(a, a + n, cmp);
printf("%d %d\n", display(a),display(s));
return 0;
}
最终代码
#include<bits/stdc++.h>
using namespace std;
int a[1001], b[1010];
int n, m;
bool cmp(int x, int y)
{
return x > y;
}
int main()
{
cin>>n;
for(int i = 0; i < n; i++)
{
cin>>a[i];
b[i] = a[i];
}
int maxsum = 0, minsum = 0;
while(n > 1)
{
sort(a, a + n);
sort(b, b + n, cmp);
m = n;
a[0] = a[0] + a[1];
minsum += a[0] - 1;
n--;///长度减一
for(int i = 1; i < n; i++)///a[0]不动,原a[1]以后的都向前一位覆盖
a[i] = a[i + 1];///所有的数前移一位
b[0] = b[0] + b[1];
maxsum += b[0] - 1;
m--;
for(int i = 1; i < m; i++)
b[i] = b[i + 1];
}
cout<<maxsum<<" "<<minsum<<endl;
return 0;
}
/***************************************************
User name:
Result: Accepted
Take time: 32ms
Take Memory: 248KB
Submit time: 2019-10-13 13:02:33
****************************************************/