问题分析
r[n][n]存储每一阶段的路径的计算结果
path[n][n]存储下一步最优结点列坐标
(2)计算:阶段性最优
r[i][j] = max{ r[i+1][j] , r[i + 1][j + 1] } + data[i][j] i=n-2,...,1 ;j<=i
下一最优子节点的列坐标
path[i][j] = 0 if r[i+1][j] >= r[i+1][j+1] and 0
path[i][j] = 1 if r[i+1][j] < r[i+1][j+1] and 0
最优解:data[1][1] -> data[2][j] -> data[i+1][j]->....., i=j=1,j=j+path
最优值 r[1][1]
子集合最优的决策和记录路径
算法设计与描述 |
算法分析 |
输入:数塔data[n][n] | (1) |
输出:结点权值最大路径,及其值 | |
void datatower(int data[][N], int n) //先是最底层 也就是第一层的数,直接赋值给 //第二层到最后一层,也是阶段 //现阶段最优值计算 } |
代码:
#include
using namespace std;
//数塔
//原结点
int const n=5+1;
int data[n][n]={{0},{0,8},{0,11,14},{0,10,5,8},{0,3,17,9,4},
{0,18,7,12,6,16}};
void show(int a[][n])
{
for(int i=1;i0;i--)//逐层向上
{
for(int j=1;j<=i;j++)//当前层,也就是当前阶段的最优解计算
{
if(r[i+1][j]>r[i+1][j+1])
//当前层的下一层 类似于左右子节点进行比较
//选择较大的
{
r[i][j]=r[i+1][j]+data[i][j];
path[i][j]=0;//选择左节点
}
else
{
r[i][j]=r[i+1][j+1]+data[i][j];
path[i][j]=1;//选择左节点
}
}
}
//输出权值最大的路径及最大权值
cout<<"max :"<";
j=j+path[i][j];
}
cout<<"["<[2,1]11-->[3,1]10-->[4,2]17-->[5,3]12
*/
#include
using namespace std;
//数塔
//原结点
int const n=5+1;
int data[n][n]={{0},{0,8},{0,11,14},{0,10,5,8},{0,3,17,9,4},
{0,18,7,12,6,16}};
void tower(int data[][n])
{
int i,j;
int r[n];//存每一行的数据
//每一次实际上都是比较刷新后的底层数据(加和之后)
//因此可以用一维数组进行存储
//这种比较是破坏性的 ,只需要最新的数据
int col[n][n]={0};
//这个不能用一维数组代替,因为
//最后是从顶向下进行找列坐标 ,然而比较是从底向上
//因此需要之前的数据
//差不多这个意思
//最底层的数据
for(i=0;i0;i--)
{
for(j=1;j<=i;j++)
{
//比较左右子结点
if(r[j]>r[j+1])
{
r[j]=r[j]+data[i][j];
//左结点大 记录左节点 用数据记录
col[i][j]=0;//第i层的选择
}
else//右结点大 记录右结点
{
r[j]=r[j+1]+data[i][j];
col[i][j]=1;//第i层的选择
}
}
}
//结束
cout<<"max:"<";
j=j+col[i][j];
}
}
int main()
{
tower(data);
return 0;
}
(2)存储 设有m个项目,共投资n万元。最多m个阶段。
(3)求解最优方案
#include
using namespace std;
void output(int a[])
{
for(int i=0;i<100;i++)
{
// if(a[i]!=0)
cout<>f[j];//第一组收益
f[j]=temp[0][j];
g[j]=f[j];//第一阶段
a[1][j]=j;//第一阶段最优配额
}
for(k=2;k<=m;k++)//从第2个项目开始的各个收益
{
for(i=0;i<=n;i++)
{
t[i]=f[i];//保存上一个的值
// cin>>f[i];//当前项目投入i万元的收益
f[i]=temp[k-1][i];
a[k][i]=0;
}
//k个项目 总共投资i万元
for(i=0;i<=n;i++)
{
for(j=0;j<=i;j++)//投资从0到i万元
{
//共投资i万元
//如果投资项目k j万元+投资其他(其他默认是最优)i-j万元,
//> t[i]投资i
if(f[j]+g[i-j]>t[i])//计算当前最优值
{
t[i]=f[j]+g[i-j];
// cout<0;i--)//从第m个项目到第1个项目 遍历所有项目
{
gain[i]=a[i][rest];
rest=rest-gain[i];
}
// output(gain);
cout<<"最优方案:"<
则 (y2,...,yn)是(2)式的一个最优解。
【这就是最优子结构】
此时
矛盾,得证。
(2)存储
第1阶段,新增物品i=1,有
内在规律:
1.保证可以连乘:列=行
2.运算次数:
算法设计与描述
#include
using namespace std;
int n=4;
int r[100]={0,5,20,50,1,100};//保存矩阵大小
int com[100][100]={0};//保存矩阵编号
int temp[100][100];//保存Mij最优计算量
int cou(int i,int j)
{
cout<"<=0)//已经计算过
{
//因为是从小到大,所以没有覆盖
return temp[i][j];
}
if(i==j)//此时 Mii 也就是同一个矩阵
{
temp[i][j]=0;//所需计算量为0
// com[i][j]=0;//此时分割点,已经在初始化时赋值了
return temp[i][j];
}
if(i+1==j)//两个矩阵相乘 结果固定
{
temp[i][j]=r[i]*r[i+1]*r[i+2];
com[i][j]=i;//此时分割点的下标 是i
return temp[i][j];
}
//其他情况 此时有多个情况
//其中一个选择,作为基准值
int x=cou(i,i)+cou(i+1,j)+r[i]*r[i+1]*r[j+1];//0增益+已知增益+新增增益
com[i][j]=i;//记录这种分割点
int y;
for(int k=i+1;k
//非递归
void fei()
{
int n=4;
int r[10]={0,5,20,50,1,100};//Mi 是矩阵ri*ri+1
int com[10][10]={0};//保存矩阵编号
int m[10][10]={0};//m[i][j]是Mi***Mj的最小乘法次数
for(int i=1;i<=n;i++)//M1 -- M4
{
m[i][i]=0;//一个矩阵
m[i][i+1]=r[i]*r[i+1]*r[i+2];//两个矩阵相乘 M1 M2
com[i][i+1]=i;//分割点是i
}
//三及以上个矩阵 Mij
for(int j=1;j<=n;j++)
// for(int i=2;i<=n;i++)//一共i个矩阵
{
for(int i=2;i<=n;i++)
// for(int j=1;j<=n;j++)
{
if(i+j-1>n)continue;
//Mj Mj+1 M..Mj+i-1
//此时Mj开始 一共i(3->n)个矩阵 前i-1个矩阵已经乘完 因此间隔点应是[j+i-2] Mj...Mj+i-2*Mj+i-1
//Mj j+i-1
m[j][j+i-1]=m[j][j]+m[j+1][j+i-1]+r[j]*r[j+1]*r[j+i];
com[j][j+i-1]=i;
// m[j][j+i-1]=m[j][j+i-1]+r[j]*r[j+i-1]*r[j+i];
// com[j][j+i-1]=j+i-2;//间隔点
int temp;
for(int k=j+1;k<=j+i-1;k++)//间隔点 下标
{
temp=m[j][k]+m[k+1][j+i-1]+r[j]*r[k+1]*r[j+i];
if(temp
1.证明具有最优子结构:
问题分析:
机器数n=5,厂子数m=3,将xi台机器给第i个厂子 效益为fi(xi) ,i=1...m
目标方程 max sum[ fi(xi)] i=1...m
s.t. sum[ xi ]=n 台机器 xi∈n xi>=0 i=1..m厂子
第一阶段:给A厂投资,g1(x)=f1(xi)
第二阶段:加入B厂,g2(x)=max{ f2(xi)+g1(x-xi) }
第三阶段:加入C厂,g3(xi)=
#include
using namespace std;
void invest()
{
int n=5;//机器
int m=3;//厂子
int profit[10][10]={{0},{3,5,4},{7,10,6},{9,11,11},{12,11,12},{13,11,12}};
// fit[i][j] i台机器对厂子j的盈利
int machine[10][10]={0};//最大利益时,一共i台机器 给j厂machine[i][j]台
int tempinitprofit[10];//当前阶段最大利益
int tempmaxprofit[10];
int tempplan[10]={0};//当前阶段最优计划
int maxmachine[10];//最终计划
//一台厂子时
for(int i=0;i<=n;i++)
{
tempinitprofit[i]=profit[i][0];
tempmaxprofit[i]=profit[i][0];
machine[1][i]=i;
}
for(int k=2;k<=m;k++)
{
//加入厂子k
//初始化
for(int i=0;i<=n;i++)
{
tempinitprofit[i]=tempmaxprofit[i];//实际是上一阶段的最大利润
tempmaxprofit[i]=profit[i][k-1];
machine[k][i]=0;
// cout<tempplan[i])
{
tempplan[i]=tempmaxprofit[j]+tempinitprofit[i-j];
// cout<0;i--)
{
maxmachine[i]=machine[i][rest];
rest=rest-maxmachine[i];
}
//输出
cout<<"最佳方案:"<