洛谷-纪念品分组(1094)
问题分析:
根据问题描述,得出最优解应该满足分组尽可能少。此外要求,每组至多两件物品且价值尽量均匀,而且还不能超过规定价格。
找出问题所在,解便不难得出。倘若价值最大的和价值最小的都没有超过规定价格,则次小和次大两两组合也能满足要求。如若不能,则价值最大的便自己单独一组,最小的和次大的组合再次比较,看是否满足要求。
代码示例:
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int w, n;
cin >> w >> n;
int value[n];
for(int i = 0; i < n; i++){
cin >> value[i];
}
sort(value, value+n);
int i =0, j = n-1, count = 0;
while(i <= j){
if(value[i] + value[j] <= w){//寻找价值较大的同价值较小的组合
j--;
i++;
} else {//价值较大的单独放置
j--;
}
count++;
}
cout << count;
return 0;
}
上述代码,对程序执行贡献最大的是一次排序,需要O(nlogn)的时间,因此时间复杂度为O(nlogn)。
洛谷-合并果子(1090)
最大整数
问题分析:
典型的贪心求解问题,问题的最优解要求得到的整数最大。因此每次局部求解过程中,都应该找到序列中的最大值。这里的局部最大值,并非真正意义上的最大值,而是应该选择每个数的第1、2、3……位上的数值尽可能大的数。例如123和72,在实际意义上,123>72,但是本题,72的首位是7,123首位是1,显然7>1,因此应首选72,而不是123。
代码示例:
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(string a, string b){
if(a + b > b + a) return 1;
else return 0;
}
int main(){
int n;
cin >> n;
string ars[n];
string res = "";
for(int i = 0; i < n; i++)
cin >> ars[i];
sort(ars, ars + n, cmp);
for(int i = 0; i < n; i++)
res += ars[i];
cout << res;
return 0;
}
美元汇率
问题分析:
初看题目,想的太复杂,原因在于以下此种情况的考虑:
样例:5
400 600 300 500 300 250
如上例,第一天购买,但相邻的第二天却不符合,是否需要继续向后匹配?开始的想法是需要。但是分析发现,题目要求最大收益,什么情况收益最大?==稳赚不赔的情况下进行尽量多次数的交换。==仍如上例情况,第二天买,第三天卖的收益肯定是大于第一天的,原因在于第二天能够买到的马克大于第一天(第二天与第三天的差值要更大-利润空间更大)。
代码示例:
#include<cstdio>
using namespace std;
int main(){
int n;
scanf("%d", &n);//天数
int m[n];
double t = 100.0;
for(int i = 0; i < n; i++){
scanf("%d", &m[i]);
}
for(int i = 0; i < n-1; i++){
if(m[i] > m[i+1])
t *= (double)m[i]/m[i+1];
}
printf("%.2f", t);
return 0;
}
/*
5
400 300 500 300 250*/
零件分组:
问题分析:
题目要求对零件长度和重量分组,且长度和重量皆呈不下降趋势。
法一:可以先确保长度或重量二者之一呈不下降趋势(排序实现)。另一属性可以采用暴力遍历求解:遍历序列,直至没有逆序对为止。举个例子,如下图所示:
如图所示,已按其中之一属性排序,因此只需要求解对立属性序列即可。遍历第二行序列,若存在逆序对(8,4即为逆序对)则分组记录加1,暴力扫描直至不存在逆序对。我们可以设置一个布尔类型数组,若元素满足条件(呈不下降趋势)则可以设置数组为false,表示此数组已加入一个分组。例如,3 < 5 < 8满足条件,因此三个加入一组(布尔类型数组置false,表示已从待排序列中删除),此组中的最大值已为8,后续序列无满足情况,所以需要重新安排一组。
代码示例:
#include<iostream>
#include<algorithm>
using namespace std;
struct A{
int h, w;
};
bool cmp(A x, A y){
if(x.h == y.h) return x.w < y.w;
return x.h < y.h;
}
int main(){
int n, count = 0, b = 0, b2 = -1;
cin >> n;
bool visted[n];
bool flag = true;
A a[n];
for(int i = 0; i < n; i++){//init
visted[i] = true;
cin >> a[i].h >> a[i].w;
}
sort(a, a+n, cmp);
while(b != b2){
b2 = b;
count++;
int t = a[b].w;
for(int i = b+1; i < n; i++){
if(a[i].w >= t && visted[i]){
t = a[i].w;
visted[i] = false;
} else if(a[i].w < t && flag){
b = i;
flag = false;
}
}
flag = true;
}
cout << count;
return 0;
}