棋盘移动

/*
计划聚会:问题描述:就是对于一个公司而言的话形成的管理体系是如下的情况:以总裁为根的一棵树,之后往下进行扩展,分左子树以及右子树,现在要求的是
每一层的每一个节点都有一个对聚会的喜欢程度,但是限制条件是雇员和他的直接上司是不可以同时参加的,现在就是求这个的期望总和是最大的情况;

  解法:我们对于某一层的一个节点进行讨论,如果该节点参加的话,把这个节点涂色为红色,不参加的话涂色为白色,对应的可以得到的是一个涂色的树,那么的话
对于这个树的期望程度可以表示为T(x,c)其中x表示为节点,c对应的为它的颜色,那么的话,对应的节点的期望程度是v(书上说这是一个常量),相应的可以计算出节点
的期望程度公式是:1,如果是叶子节点,即x下面没有其他的节点:T(x,c)=v(如果红色,即不参加)或者0(如果白色,即参加),这就是一个最优子结构;2.当是非叶子节点
那么可以使用如下的式子进行计算T(x,c)=v+T(x子树们,白色):这个是当是x为红色的时候,(那么由于x参加,对应的子树必定不会参加喽)就是下面的子树使用白色操作
,2.T(x,c)=max(T(子树们,白色),T(子树们,红色)),由于是当x的颜色是白色即这个节点不参加,对应的孩子可能会参加,可能不会参加,那么的话这就是子结构了;
*/
//代码的话,简化的话对于节点的出现次序假设自己是知道的,如果是要程序自动判断的话,我们就需要涉及到二叉树,尼玛如果不是二叉树,更复杂了···这里不写
/*
棋盘上移动:问题描述:nXn的棋盘,存在着如下的关系,就是从盘底的某一个行开始,到盘顶的某一个位置位置,这就是棋盘的移动过程,棋子的移动过程要遵守的
规则是这样的,从某一个位置往上移动的话存在的三种可能性:1.直接移到(x,y)的上一个(x,y+1);2.移到(x+1,y)左上(当然是不能够有最左的情况)(x+1,y-1);3.对称的
(x+1,y-1);对于这三种情况进行分析,此外题目还说从从点x到y的距离的消费是p(x,y),那么我们如果需要达到上面的要求的话,需要让开销最大,则是怎么算的?

  解法:假设开销c[i][j],为到达点(i,j)开销。我们知道的是假设到达点(i,j)之前的话需要涉及到的点的可能性有三种,我们从这三种情况进行分析得到最后的结果:1.如果是从节点(i-1,j)往上直走到达(i,j)
2;从(i-1,j-1)往右上走到达;3.从(i-1,j+1)往左上直走到达。
对应的开销计算如下1:c[i][j]=c[i-1][j]+p[(i-1,j)][(i,j)](j>1);2.c[i][j]=c[i-1][j-1]+p[(i-1,j-1)][(i,j)];3.c[i][j]=c[i-1][j+1]+p[(i-1,j+1)][(i,j)];
(j<n)
*/

#include<iostream>
using namespace std;
#define N 10
struct money
{
	int n;//实际的矩形边长
	int c[N][N];
	int p[N][N][N][N];//这个是木有办法啊,只能先这样了;
	int w[N][N];
	money(int num):n(num){
		for (int i=0;i<=n;++i)
			for (int j=0;j<=n;++j)
			{
				w[i][j]=0;
				c[i][j]=0;
				for (int s=0;s<=n;++s)
					for (int t=0;t<=n;++t)
					{
						cin>>p[i][j][s][t];//没法子
					}
			}
	}
	void money_get();
	void print(int,int);
};

void money::money_get()
{
	int i,j;
	for (i=1;i<=n;++i)
		c[1][i]=0;
	for (i=2;i<=n;++i)
		for (j=1;j<=n;++j)
		{
			c[i][j]=-0xfffffff;
			if (j>1)
			{
				c[i][j]=c[i-1][j-1]+p[i-1][j-1][i][j];
				w[i][j]=j-1;
			}
			if(c[i-1][j]+p[i-1][j][i][j]>c[i][j])
			{
				c[i][j]=c[i-1][j]+p[i-1][j][i][j];
				w[i][j]=j;
			}
			if (j<n&&c[i-1][j+1]+p[i-1][j+1][i][j]>c[i][j])
			{
				c[i][j]=c[i-1][j+1]+p[i-1][j+1][i][j];
				w[i][j]=j+1;
			}
		}
}

void money::print(int i,int j)
{
	if(i>1)
		print(i-1,w[i][j]);
	cout<<"("<<i<<","<<j<<")"<<" ";

}

int main()
{
	money my(4);//数字太多,没有测试,应该没错
	my.money_get();
	my.print(2,4);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值