回溯法实现邮票问题

来源:互联网 发布:人大报刊资料数据库 编辑:程序博客网 时间:2024/05/21 08:04
/**
 *邮票问题
 *求最大连续区间,从邮资为1开始,步长为1
 *改进的子集合和函数 
 * @author by nowaywolf
*/


using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;


namespace Stamp
{
    
class Program
    
{
        
static int[] price = new int[1000];
        
static int m, n,r,t,current,max;
        
static int[] vec = new int[1000];
        
static bool flag = false;
        
static void Main(string[] args)
        
{
            price[
0= 0;
            Console.WriteLine(
"please enter the 面值总数:");
            n 
= Int32.Parse(Console.ReadLine());
            Console.WriteLine(
"please enter the 最大邮票张数:");
            m 
= Int32.Parse(Console.ReadLine());
            ArrayList StampPrice 
= new ArrayList();
            Console.WriteLine(
"please enter the stamp price:");
            
            
//输入n种邮票面值
            for (int i=0; i <n; i++)
            
{
                StampPrice.Add(Int32.Parse(Console.ReadLine()));
            }

            
            
//计算集合中n*m张邮票的总邮资
            for (int i = 0; i < n; i++)
            
{
                r
+= (int)StampPrice[i] * m;
            }

            
//构造一个n*m的集合
            for (int i = 0; i < n; i++)
            
{
                
for (int j = 0; j < m; j++)
                
{
                    price[
++t] = (int)StampPrice[i];
                }

            }

           
            
//对于每一个邮票值,检查是否可得到
            for (int i = 1; i <= (int)StampPrice[n-1]*m; i++)
            
{
                
if (CheckNum(01,r,i,0))
                
{
                    Console.WriteLine(
"the number "+i+" is ok!");
                }

                
if (flag&&(i==current+1))
                
{
                    Console.WriteLine(
"["+"1"+","+i+"]");
                    current 
= i;//当前值可以到达,则保存以便求连续空间
                    max = i - 1;
                }

                
else
                    
if (flag)
                    
{
                        Console.WriteLine(
"[]");
                    }

                flag 
= false;
            }

        }


        
/// <summary>
        
/// 检查邮资是否可达
        
/// </summary>
        
/// <param name="sum">用于累加的值</param>
        
/// <param name="k">向量下标</param>
        
/// <param name="r">当前邮资剩余值</param>
        
/// <param name="M">要检查的邮资</param>
        
/// <param name="count">用于控制邮票张数</param>
        
/// <returns>如果所检查邮资可达,返回flag=true;否则返回flag=false</returns>

        public static bool CheckNum(int sum,int k,int r,int M,int count)
        
{
            vec[k] 
= 1;
            
if (count >= m)//邮票张数不能超过m
            {
                
return flag;
            }

            
if ((sum + price[k]) == M)//如果找到解
            {
                flag 
= true;
                Console.WriteLine();
                
for (int i = 0; i <= k; i++)//输出该解是怎样构成的
                {
                    
if (vec[i] != 0)
                    
{
                        Console.Write(price[i] 
+ "+");
                    }

                }

                
return flag;
            }

            
else
            
{
                
if (k<m*n&&sum + price[k] + price[k + 1<= M)//k累加的次数不能超过m*n次
                {
                    CheckNum(sum 
+ price[k], k + 1, r - price[k], M, count + 1);
                }

            }

            
            
//没有找到解就回溯,如果找到了一个解就不再找其它解
            if (flag!=true&& sum + r - price[k] >= M && sum + price[k + 1<= M)
            
{
                vec[k] 
= 0;
                
//count--;
                CheckNum(sum, k + 1, r - price[k],M,count);
                
            }

           
return flag;
        }

    }

}

 
原创粉丝点击