110,536
社区成员
发帖
与我相关
我的任务
分享
private static int iGroupCnt = 0;
private static int[] arrSum;
private static int[] arrFloorSum;
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
int[] arrABC = new int[] { 54, 257, 19, 360 };
int V = 654321;
//存放x1x2x3x4
int[] arrX = new int[arrABC.Length];
//为了处理x1>x2>x3>x4的限定条件,加的2个数组
arrSum = new int[arrABC.Length];
arrFloorSum = new int[arrABC.Length];
for (int i = 0; i < arrABC.Length; i++)
{
if (i > 0)
{
arrSum[i] = arrSum[i - 1] + arrABC[i];
arrFloorSum[i] = arrFloorSum[i - 1] + arrSum[i - 1];
}
else
{
arrSum[i] = arrABC[i];
}
}
//当前处理的数的序号,右边的x值最小,从右边的数开始
//序号
int iCurIndex = arrABC.Length - 1;
//值
int iCur = arrABC[iCurIndex];
//组合次数
iGroupCnt = 0;
//遍历函数
IterateFun(arrABC, iCurIndex, arrX, V);
////如果考虑A1<=A,B1<=B,C1<=C,D1<=D的情况
////再外面加循环就行了,我给个嵌套的写法,你可以改成递归的方式,以适应ABC个数不确定
//int[] arrABC2 = new int[arrABC.Length];
//for (int i = 0; i < arrABC[0] + 1; i++)
//{
// arrABC2[0] = i;
// for (int j = 0; j < arrABC[1] + 1; j++)
// {
// arrABC2[1] = j;
// for (int m = 0; m < arrABC[2] + 1; m++)
// {
// arrABC2[2] = m;
// for (int n = 0; n < arrABC[3] + 1; n++)
// {
// arrABC2[3] = n;
// IterateFun(arrABC2, iCurIndex, arrX, V);
// }
// }
// }
//}
sw.Stop();
Console.WriteLine("组合数:" + iGroupCnt);
Console.WriteLine("花费:"+sw.ElapsedMilliseconds+"毫秒");
Console.ReadLine();
}
/// <summary>
/// 递归函数
/// </summary>
/// <param name="arrABC">ABC数组</param>
/// <param name="iCurIndex">当前序号</param>
/// <param name="arrX">x1x2数组</param>
/// <param name="VRemain">V剩余值</param>
private static void IterateFun(int[] arrABC, int iCurIndex, int[] arrX, int VRemain)
{
//当前序号对应的值
int iCur = arrABC[iCurIndex];
if (iCurIndex < 1)
{
//如果还剩下A没有计算,直接判断能否整除
int iRemainder = VRemain % iCur;
if (iRemainder == 0 )
{
int iQuotient = VRemain / iCur;
arrX[iCurIndex] = iQuotient;
//输出到屏幕中
//string s = "";
//for (int i = 0; i < arrIn.Length; i++)
//{
// s += string.Format("{0}*{1}+", arrIn[i], arrLoop[i]);
//}
//s = s.TrimEnd('+');
//Console.WriteLine(s);
iGroupCnt++;
}
}
else
{
//如果x1x2不考虑为0的情况,请将此处改为1
int iMinX = 0;
//前N项ABC之和
int iSum = arrSum[iCurIndex];
//因为x1>x2>x3>x4的限定,所以当计算x4时要减去(3x1+2x2+x3)
int iFloorSum = arrFloorSum[iCurIndex];
int iVRemainTmp = VRemain - iFloorSum;
//考虑x1>x2>x3>x4限定后,X的最大取值,包括此最大值
int iMaxX = iVRemainTmp / iSum;
//当前X最小值不能比后面的X小
if (iCur < arrX.Length - 1)
{
iMinX = arrX[iCurIndex + 1] + 1;
}
for (int i = iMinX; i < iMaxX + 1; i++)
{
arrX[iCurIndex] = i;
//遍历
IterateFun(arrABC, iCurIndex - 1, arrX, VRemain - i * iCur);
}
}
}
注释白写了,你太懒了。 只考虑A1=A,B1=B,C1=C,D1=D就大打折扣了吗。
只考虑A1=A,B1=B,C1=C,D1=D就大打折扣了吗。
V越大,ABC个数越多,ABC数值越小,组合就越多。 只考虑A1=A,B1=B,C1=C,D1=D,即54*x1+257*x2+19*x3+360*x4=654321,限定条件 x1>x2>x3>x4,且x4>0的情况下, 用递归算了一下,组合有40375394种。用时64秒左右(把打印部分注释掉了),这个应该没有什么算法,只能递归吧?private static int iGroupCnt = 0; private static int[] arrSum; private static int[] arrFloorSum; static void Main(string[] args) { Stopwatch sw = new Stopwatch(); sw.Start(); int[] arrABC = new int[] { 54, 257, 19, 360 }; int V = 654321; //存放x1x2x3x4 int[] arrX = new int[arrABC.Length]; //为了处理x1>x2>x3>x4的限定条件,加的2个数组 arrSum = new int[arrABC.Length]; arrFloorSum = new int[arrABC.Length]; for (int i = 0; i < arrABC.Length; i++) { if (i > 0) { arrSum[i] = arrSum[i - 1] + arrABC[i]; arrFloorSum[i] = arrFloorSum[i - 1] + arrSum[i - 1]; } else { arrSum[i] = arrABC[i]; } } //当前处理的数的序号,右边的x值最小,从右边的数开始 //序号 int iCurIndex = arrABC.Length - 1; //值 int iCur = arrABC[iCurIndex]; //组合次数 iGroupCnt = 0; //遍历函数 IterateFun(arrABC, iCurIndex, arrX, V); ////如果考虑A1<=A,B1<=B,C1<=C,D1<=D的情况 ////再外面加循环就行了,我给个嵌套的写法,你可以改成递归的方式,以适应ABC个数不确定 //int[] arrABC2 = new int[arrABC.Length]; //for (int i = 0; i < arrABC[0] + 1; i++) //{ // arrABC2[0] = i; // for (int j = 0; j < arrABC[1] + 1; j++) // { // arrABC2[1] = j; // for (int m = 0; m < arrABC[2] + 1; m++) // { // arrABC2[2] = m; // for (int n = 0; n < arrABC[3] + 1; n++) // { // arrABC2[3] = n; // IterateFun(arrABC2, iCurIndex, arrX, V); // } // } // } //} sw.Stop(); Console.WriteLine("组合数:" + iGroupCnt); Console.WriteLine("花费:"+sw.ElapsedMilliseconds+"毫秒"); Console.ReadLine(); } /// <summary> /// 递归函数 /// </summary> /// <param name="arrABC">ABC数组</param> /// <param name="iCurIndex">当前序号</param> /// <param name="arrX">x1x2数组</param> /// <param name="VRemain">V剩余值</param> private static void IterateFun(int[] arrABC, int iCurIndex, int[] arrX, int VRemain) { //当前序号对应的值 int iCur = arrABC[iCurIndex]; if (iCurIndex < 1) { //如果还剩下A没有计算,直接判断能否整除 int iRemainder = VRemain % iCur; if (iRemainder == 0 ) { int iQuotient = VRemain / iCur; arrX[iCurIndex] = iQuotient; //输出到屏幕中 //string s = ""; //for (int i = 0; i < arrIn.Length; i++) //{ // s += string.Format("{0}*{1}+", arrIn[i], arrLoop[i]); //} //s = s.TrimEnd('+'); //Console.WriteLine(s); iGroupCnt++; } } else { //如果x1x2不考虑为0的情况,请将此处改为1 int iMinX = 0; //前N项ABC之和 int iSum = arrSum[iCurIndex]; //因为x1>x2>x3>x4的限定,所以当计算x4时要减去(3x1+2x2+x3) int iFloorSum = arrFloorSum[iCurIndex]; int iVRemainTmp = VRemain - iFloorSum; //考虑x1>x2>x3>x4限定后,X的最大取值,包括此最大值 int iMaxX = iVRemainTmp / iSum; //当前X最小值不能比后面的X小 if (iCur < arrX.Length - 1) { iMinX = arrX[iCurIndex + 1] + 1; } for (int i = iMinX; i < iMaxX + 1; i++) { arrX[iCurIndex] = i; //遍历 IterateFun(arrABC, iCurIndex - 1, arrX, VRemain - i * iCur); } } }
單單這些條件還不夠吧,數字的正負或者數字為整型還是浮點型都沒有明確說明。