求一算法:在m个整数中,求n个数的组合,若这n个数的和等于sum,则将这n个数打印出来。(m,n均不定,1<=n<=m,m个数的值,sum的值由界面输入.)
看起来好像很简单,实际写起来好像还有点复杂,希望各位提供算法和代码,(兼顾一下算法的效率,若m的值比较大,怎么办?总不至于在机器面前等上几十分钟吧?m的值小于100,平常一般在20左右.)不胜感激!!!!!
a:我记得以前有写过的
具体方法如下
1,进行排序,从小到大
2,先拿一位数进行判断,如果后面的数大了,退出
3,拿二位数进行判断,从第一个开始,然后配对的是后面的数,如果大,退出,然后拿第2个数,
递归实现以后的吧,
反正是找到退出条件,
b:所有可能的组合
还是只要一组
下面可得到一个组合
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Edit1: TEdit;
procedure FormCreate(Sender: TObject);
procedure Sum(a: array of Integer; x: Integer);
procedure Button1Click(Sender: TObject);
function knap(S, n: Integer): Integer;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
a: array [0..25] of Integer;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
for i := 0 to 25 do
begin
Randomize();
a[i] := Abs(Random(50));
end;
end;
procedure TForm1.Sum(a: array of Integer; x: Integer);
var
i,j,temp: Integer;
begin
if ( knap(50,i) > 0 )then Memo1.Lines.Add( 'OK')
else continue;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
i,j,temp: Integer;
begin
for i := Low(a) to High(a) -1 do
for j:= i+1 to High(a) do
begin
if a[i] > a[j] then
begin
temp := a[i];
a[i] := a[j];
a[j] := temp;
end;
end;
Sum(a, 50);
end;
function TForm1.knap(S, n: Integer): Integer;
begin
if(S = 0) then
begin
result := 1;
exit;
end;
if ( (s< 0)or ( (s>0) and (n < 1) )) then
begin
result := 0;
exit;
end;
if (knap(s-a[n], n-1) > 0) then
begin
Memo1.Lines.Add(IntToStr(a[n]));
result := 1;
exit;
end;
Result := knap(s,n-1);
end;
end.
2.
输入为“1,3,5,7,9”这5个
输出为
1,3,5
1,3,7
1,3,9
1,5,7
1,5,9
1,7,9
3,5,7
3,5,9
3,7,9
5,7,9
该怎么实现这个算法?
//C++ Code;
//you can change
int index[4]; //used to record the indexes of the selected
int cur; //record the number with the lowest index to be selected
cur = 0;
void fun(int *index,int step)
{
step++;
if(step>3)
{
cout<<array[index[1]]<<" "<<array[index[2]]<<........... //print the result
return;
}
else if(step<=3)
{
for(i=cur;i<5;i++)
{
int tmp = cur;
index[step] = cur;
cur++;
fun(index,step);
cur = tmp;
}
}
}
void main()
{
fun(index,0);
}
3.
编程实现1到N个数的所有排列组合
如:
n = 3
则得到的序列如下:123, 132, 213, 231, 312, 321
我的实现如下,大家看看如何:
2
3
4
5
6
4.
题目描述:
有3种面额的硬币:1分,2分和5分的。现在有100枚这样的硬币,面额总和是2.47元,求共有多少种可能,且1分,2分和5分的硬币各有多少。
解题思路:
假设1分,2分和5分的硬币个数分别是x,y,z个。
则有:
x + y + z =100
x+2y+5z=247
可得:
X = 3z – 47
Y = 147-4z
又知道
x >= 0
y>=0
z>=0
5z<=247
可得:
16<=z<=36
问题得解。
问题的证明:
用c#代码实现,并输出每种解的值。
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int num = CaluSovNum();
}
private static int CaluSovNum()
{
int x, y, z;
int num = 0;
for (z = 16; z <= 36; z++)
{
x = 3 * z - 47;
y = 147 - 4 * z;
if (x <0 || y <0 || x + y + z != 100 || x + 2 * y + 5 * z != 247)
{
throw new Exception("Error");
}
num++;
Console.WriteLine("1分钱的硬币个数是{0}, 2分钱的硬币个数是{1}, 5分钱的硬币个数是{2}",
x, y, z);
}
return num;
}
}
}
http://www.cnblogs.com/gpcuster/archive/2007/12/19/1005666.html