C++程序 石子合并问题 - 范文中心

C++程序 石子合并问题

01/26

问题描述:

在一个圆形操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。

试设计一个算法,计算出将n 堆石子合并成一堆的最小得分和最大得分。

【输入文件】

包含两行,第1 行是正整数n (1

第2行有n 个数,分别表示每堆石子的个数。

【输出文件】

输出两行。

第1 行中的数是最小得分;第2 行中的数是最大得分。

【输入样例】

4

4 4 5 9

【输出样例】

43

54

设计算法分析:

1)、此题表面上看是用贪心算法比较合适,实则不然,用贪心算法是每次都合

并得分最大的或最小的相邻两堆,但不一定保证余下的合并过程能导致最优解,聪明的读者马上会想到一种理想的假设:如果N -1次合并的全局最优解包含了每一次合并的子问题的最优解,那么经这样的N -1次合并后的得分总和必然是最优的,这就是动态规划的思想。

采用动态规划求解的关键是确定所有石子堆子序列的最佳合并方案。

这些石子堆子序列包括:{第1堆、第2堆}、{第2堆、第3堆}、……、{第N 堆、第1堆};{第1堆、第2堆、第3堆}、{第2堆、第3堆、第4堆}、……、{第N 堆、第1堆、第2堆};……{第1堆、……、第N 堆}{第2堆、……、第N 堆、第1堆}……{第N 堆、第1堆、……、第N -1堆}

为了便于运算,我们用〔i ,j 〕表示一个从第i 堆数起,顺时针数j 堆时的子序列{第i 堆、第i +1堆、……、第(i +j )堆}(注意: 此时的i+j 可能已经超出N 的范围,为此 我们在读入每堆石子的数量时,把石子堆数扩展为2*N-1,有a[i]=a[i+N],没有a[N+N])

它的最佳合并方案包括两个信息:

② 该子序列的各堆石子合并成一堆的过程中,各次合并得分的总和;

②形成最佳得分和的子序列1和子序列2。由于两个子序列是相邻的, 因此只需记住子序列1的堆数;

读者可以从以下详细的程序代码中体会到算法的思想:

// StonesMerger.h

#ifndef STONESMERGER_H

#define STONESMERGER_H

class StonesMerger

{

public:

StonesMerger();

~StonesMerger();

void run(); // 运行 接口

private:

int number; // 石子的堆数

int totalMax; // 记录合并成一堆的最 大 得分

int X; // 记录合并成一堆的最 大 得分的 最优合并的起始堆

int totalMin; // 记录合并成一堆的最 小 得分

int Y; // 记录合并成一堆的最 小 得分的 最优合并的起始堆

int *a; // 存储 石子的 数量

int **MAX; // 记录子序列合并最 大 得分

int **Smax; // 记录子序列合并最 大 得分的 最佳断开位置

int **min; // 记录子序列合并最 小 得分

int **smin; // 记录子序列合并最 小 得分的 最佳断开位置

bool input(); // 输入 接口 读取 input.txt 文件

void mostValue(); // 以第 i 堆开始 合并后面的 j 堆 j=0、1、

2、...... 、n-1

void output(); // 输出 显示

void traceback(int **s,int n,int m); //

smin[n][m] 寻找轨迹

};

#endif

// StonesMerger.cpp

#include

#include

#include

#include

#include "StonesMerger.h"

ifstream inputFile("input.txt",ios::in);

ofstream outputFile("output.txt",ios::out);

对应于或 Smax[n][m]

#define N 100 // 根据实际问题规模 大小 设定 恰当的 初值

StonesMerger::StonesMerger()

{

number=0;

X=0;

Y=0;

totalMax=0;

totalMin=0;

a=new int [2*N];

MAX=new int *[2*N];

Smax=new int *[2*N];

min=new int *[2*N];

smin=new int *[2*N];

for (int i=0;i

{

min[i]=new int [2*N]; MAX[i]=new int [2*N]; Smax[i]=new int [2*N];

}

}

smin[i]=new int [2*N];

StonesMerger::~StonesMerger()

{

delete []a;

for (int i=0;i

{

}

delete []MAX;

delete []Smax;

delete []min;

delete []smin;

}

delete []MAX[i]; delete []Smax[i]; delete []min[i]; delete []smin[i];

void StonesMerger::run() // 运行 接口

{

if (input())

{

}

}

bool StonesMerger::input()

{

if (!inputFile)

{

}

if (!outputFile)

{

}

mostValue(); output(); cerr

inputFile>>number;

outputFile

outputFile

for (int i=1;i

{

}

outputFile

if (a!=NULL)

{

}

return false;

}

void StonesMerger::output()

{

outputFile

traceback(smin,Y,number);

inputFile>>a[i]; a[i+number]=a[i]; outputFileoutputFile

outputFile

traceback(Smax,X,number);

outputFile

}

void StonesMerger::mostValue() // 寻找 最优 断开位置 和 最大 / 最小子序列

{

for (int i=1;i

{

}

for (int r=2;r

{

for (int i=1;i

int j=i; for (int m=1;m

if (T2

smin[i][r]=k;

}

} if (T1>MAX[i][r]) { } } } MAX[i][r]=T1; // 确保 子序列 最优 记录 最优断开位置 Smax[i][r]=k;

totalMax=0;

for (i=1;i

{

if (MAX[i][number]>totalMax) // 寻找 最大得分 并记录 最大得分的 序列的起始位置

}

totalMin=totalMax;

http://asizahuodian.taobao.com

{ totalMax=MAX[i][number]; X=i; }

for (i=1;i

{

if (min[i][number]

{

totalMin=min[i][number];

Y=i;

}

}

}

void StonesMerger::traceback(int **s,int i,int r) // 寻找轨迹

{

if (r==1)

{

outputFilenumber ? i%number : i);

}

else if(r==2)

{

outputFilenumber ? i%number

i)number ? (i+1)%number : (i+1))

}

http://asizahuodian.taobao.com

:

else

{

}

}

// main,cpp

#include "StonesMerger.h"

int main()

{

StonesMerger sm;

sm.run();

return 0;

}

http://asizahuodian.taobao.com

outputFile


相关内容

  • 逆向 C -- 识别类及其构造函数 - FISH 的专栏 - CSDNBlog
    逆向 C++ 这些年来,逆向工程分析人员一直是凭借着汇编和 C 的知识对大多数软件进行逆向工程的,但是,现在随着越来越多的应用程序和恶意软件转而使用 C++语言进行开发,深入理解 C++ 面向对象方式开发的软件的反汇编技术就显得越发的必要. ...
  • 我的最小项目管理工具集
    工具从来就乱花迷眼,但花哨的工具未必适合自己的团队. 洗净铅华的总结出一些最必要的,能提供最大辅力加持的工具. 参见<死亡中旅>2nd 第x章--最小工具集. 1.版本管理工具和文本比较/合并工具 用的是CVS: 绿毛小海龟加 ...
  • 测绘程序设计课程实习报告模板
    一.实习目的 <测绘程序设计>是一门理论与实践并重的课程,课程设计是测量数据处理理论学习的一个重要实践环节,可以看做是在学习了专业基础理论课<误差理论与测量平差基础>课程后进行的一门实践课程,其目的是增强学生对测量平 ...
  • 写给计算机专业的大学生
    写给计算机专业的大学生(转) 252538746 偶尔在网上看见了这样的一篇文章,希望正在学习计算机的大家可以认真的把它看完 1416718715 "首先说一说进入计算机专业的目的,我个人是因为十分喜欢IT业,很喜欢折腾电脑,所以 ...
  • 计算机世界最具影响力的20人
    转自: 计算机世界最具影响力的20人 1.约翰•冯•诺依曼 (John Von Neuman, 1903- 1957) 被誉为"电子计算机之父".他对人类的最大贡献是对计算机科学.计算机技术和数值分析的开拓性工作,194 ...
  • c++电影院管理系统的设计
    内蒙古科技大学 课程设计论文 题 目:C++课程设计 --电影院售票管理系统 学生姓名:张雪婉 学 号:1167119224 专 业:通信工程 班 级:2011-2 指导教师:郝斌 [摘要]......................... ...
  • 学生籍贯信息记录簿
    <学生籍贯信息记录簿> 程 序 设 计 基 础 课 程 设 计 报 告 专业: 电子信息工程 班级:2班 姓名:左磊 学号:2006081992 指导老师:常耀辉 二00八年7月3日 目 录 1 程序设计的目的--------- ...
  • 从此乱码是路人
    相信大家在刚学 Qt 的时候一定遇到过 #include #include #include int main(int argc, char *argv[]) { QApplication a(argc, argv); QLabel lb; ...
  • 用C语言来实现的类似C++函数的重载特性
    用C语言来实现的类似C++函数的重载特性-----void*指针闲谈 分类:c/c++ 2007-11-01 20:09 527人阅读评论(3)收藏举报 c++语言cbuffer 我们在使用C库函数的时候经常会碰到使用void*指针的现象, ...
  • 电脑文件格式大全
    386 Windows虚拟设备驱动程序 CDX 复合索引文件 ABC ASCII编码格式文件 CFG 配置文件,包含系统设备和环境信息 ACM 音频压缩管理驱动程序 CGM Paint Shop Pro映象文件 ACT 文档向导 CHK 被 ...