贪心算法求所有分解方法中各加数乘积的最大值
2016-11-13 18:01
267 查看
设n为一自然数,n可以分解成若干个不同的自然数的和,这样的分法有很多种,比如n=10, 10可以分解为:10=5+4+1; 10=5+3+2; 10+9+1; 10=8+2; 10=7+3; 10=6+4; 10=7+2+1; 10=6+3+1;…。在所有这些分法中,各加数乘积最大的为30,(10=5+3+2中加数的乘积为5*3*2=30)。试编写程序,求各种分解方法中各加数乘积的最大值。
输入要求:输入只有1行,自然数n。
输出要求:输出也只有1行,所有分解方法中各加数乘积的最大值。
题目已经要求不同自然数,因此根据数学原理,分解的数越接近,它们的乘积是最大的,而且不要分解出1,至少从2开始。
所以从2开始依次递增,直到最后的和大于该数,由于数是按递增排列的,故如果最后拆解的数不是递增的话则将其依次递减加到前面较大的数中,因为为了保证分解的数接近而且较大的数增加的多效果更好。
参考代码:
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <ctime>
#define fur(i,a,b) for(int i=(a);i<=(b);i++)
#define furr(i,a,b) for(int i=(a);i>=(b);i--)
#define cl(a,b) memset((a),b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const int mod=1000000007;
const double pi=acos(-1.0);
const int N = 1000;
int s
= { 0 };
int top;
int sum;
int n,k,m;
int time_
= { 0 };
int min_t;
void dfs(int x)//先用dfs求出所有可能的加数
{
int i;
int temp=0;
if (sum == m) {
for (int p = 0; s[p] != 0; p++)
{
if (s[p] > k || p >= n) return;
temp += time_[p][s[p]];
}
if (temp < min_t)
min_t = temp;
return;
}
if (sum>m)return;
for (i = 1; i <= m; i++)//从1开始实现所有顺序
{
sum += i;
s[top++] = i;
dfs(i);
sum -= i;
s[top--] = 0;
}
}
void MinTimeSolute()
{
min_t = mod;
top = 0;
sum = 0;
dfs(1);
}
int main(){
while (scanf("%d %d %d", &n, &k, &m)==3)
{
for (int i = 0; i < n; i++)
for (int j = 1; j <= k; j++)
scanf("%d", &time_[i][j]);
MinTimeSolute();
printf("%d", min_t);
}
return 0;
}
输入要求:输入只有1行,自然数n。
输出要求:输出也只有1行,所有分解方法中各加数乘积的最大值。
题目已经要求不同自然数,因此根据数学原理,分解的数越接近,它们的乘积是最大的,而且不要分解出1,至少从2开始。
所以从2开始依次递增,直到最后的和大于该数,由于数是按递增排列的,故如果最后拆解的数不是递增的话则将其依次递减加到前面较大的数中,因为为了保证分解的数接近而且较大的数增加的多效果更好。
参考代码:
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <ctime>
#define fur(i,a,b) for(int i=(a);i<=(b);i++)
#define furr(i,a,b) for(int i=(a);i>=(b);i--)
#define cl(a,b) memset((a),b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const int mod=1000000007;
const double pi=acos(-1.0);
const int N = 1000;
int s
= { 0 };
int top;
int sum;
int n,k,m;
int time_
= { 0 };
int min_t;
void dfs(int x)//先用dfs求出所有可能的加数
{
int i;
int temp=0;
if (sum == m) {
for (int p = 0; s[p] != 0; p++)
{
if (s[p] > k || p >= n) return;
temp += time_[p][s[p]];
}
if (temp < min_t)
min_t = temp;
return;
}
if (sum>m)return;
for (i = 1; i <= m; i++)//从1开始实现所有顺序
{
sum += i;
s[top++] = i;
dfs(i);
sum -= i;
s[top--] = 0;
}
}
void MinTimeSolute()
{
min_t = mod;
top = 0;
sum = 0;
dfs(1);
}
int main(){
while (scanf("%d %d %d", &n, &k, &m)==3)
{
for (int i = 0; i < n; i++)
for (int j = 1; j <= k; j++)
scanf("%d", &time_[i][j]);
MinTimeSolute();
printf("%d", min_t);
}
return 0;
}
相关文章推荐
- 贪心算法----正整数分解问题 和相同,乘积最大
- 整数分解成不同加数的最大乘积
- 输出正整数分解的所有数的最大乘积
- 给定一个正整数n,则在n所有的分解式中,求因子乘积最大的一个分解及此乘积。
- 有一个正整数N可以分解成若干个正整数之和,问如何分解能使这些数的乘积最大?
- 给一个整数数组,对数组中的每个整数中的所有数字按照升序排列(如101排序后为011)请写一个方法,输出排序后的数组中的最大数。 例如有一个数组: 101、132、375,排序后11、123、357,
- sdut 1293 乘积最大的分解
- (Relax 水题1.2)POJ 1032 Parliament(将n分解成若干个互不相等的整数的和,并且是这些整数的乘积最大)
- (Relax 水题1.2)POJ 1032 Parliament(将n分解成若干个互不相等的整数的和,并且是这些整数的乘积最大)
- SDUT-1293乘积最大的分解
- SQL取出某列最大值的所有记录(行)的一种方法:select count(*) from tb where c > a.c
- 有一个整数n,将n分解成若干个整数之和,问如何分解能使这些数的乘积最大,输出这个乘积m
- 乘积最大的分解
- 数和分解,乘积最大-vijos整数分解(版本2)
- 数字分解为不同自然数的最大乘积
- 获取数据表分组的最大值所在行所有信息的方法
- poj 1032 Parliament 把自然数N分解成若干个互不相同的正整数,使乘积最大;
- “超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。”问题的解决方法
- 将正整数n划分成k个不同正整数的乘积,输出所有划分方法
- 三人年龄 三个神秘蒙面人来访F博士。博士询问他们年龄时,他们说:我们中年龄最小的不超过19岁。我们3人年龄总和为70岁。且我们三人年龄的乘积是所有可能情况中最大的。