poj 1189 DP

本文介绍了两种解决钉子概率问题的方法。通过分析钉子的存在与否来计算从起点到达终点的概率,并采用分数形式给出最终答案。第一种方法使用位运算进行概率计算;第二种方法则通过数组记录钉子状态,利用递推公式更新概率。

题目来源


法一:

//2015/4/14

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

#define N 60

int n, m, num;
bool tra[N*N];   //表示是否有钉子,true则有,false则无
long long dp[N][N];   //因为钉子最多有50层,2<<50超出了int的表示范围,所以要用long long类型(64位整数)
long long fz, fm, ubt;   //分子, 分母 , 最大公约数

long long gcd(long long a, long long b)   //求最大公约数
{
	long long mod;
	while (b)
	{
		mod = a%b;
		a = b;
		b = mod;
	}
	return a;
}

void go()
{
	num = 0;  //表示序号
	char str[4];  //存放字符
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= i; j++)
		{
			scanf("%s", str);
			if (str[0] == '*')  //为‘*’则有钉子
			{
				tra[++num] = true;
			}
			else
			{
				tra[++num] = false;
			}
		}
	}

	memset(dp, 0, sizeof(dp));

	dp[1][1] = 1LL << n;   ////用位运算计算2 ^ n  

	for (int i = 1, sbh; i <= n; i++)
	{
		sbh = (i*(i - 1)) / 2;   //记录位置
		for (int j = 1; j <= i; j++)
		{
			if (tra[j + sbh])  //遇到钉子
			{
				//当某个位置(i, j)的钉子在,则将该位置的概率除以1 / 2再传递到(i + 1, j)和(i + 1, j + 1)两个位置
				dp[i + 1][j] += dp[i][j] / 2;  
				dp[i + 1][j + 1] += dp[i][j] / 2;
			}
			else
			{
				//如果某个位置钉子不在了,则该位置的概率垂直下落到下下层对应位置,即(i,j)处的概率直接赋予位置(I+2, j+1)
				dp[i + 2][j + 1] += dp[i][j];
			}
		}
	}

	fz = dp[n + 1][m + 1];
	fm = 1LL << n;   //用位运算计算2 ^ n  

	ubt = gcd(fm, fz);   //计算最大公约数
	if (fz == 0)
	{
		fm = ubt = 1;
	}
	printf("%I64d/%I64d\n", fz / ubt, fm / ubt);
}

int main()
{
//	freopen("E:\input.txt", "r", stdin);
	while (scanf("%d%d", &n, &m) != EOF)
	{
		go();
	}
	return 0;
}


法二:

#include "stdio.h"
#include "string.h"
#define M 55
#define ll __int64

int a[M][M],n,m;
ll dp[M][M];
char s[5];

ll gcd(ll a,ll b)
{
	if(b) 
		return gcd(b,a%b);
	return a;
}

int main()
{
//	freopen("E:\input.txt", "r", stdin);
	int i,j;
	ll ans1,ans2;
	ll k;
	while(scanf("%d%d",&n,&m)>0)
	{
		memset(dp,0,sizeof(dp));
		for(i=0;i<n;i++)
		{
			for(j=0;j<=i;j++)
			{
				scanf("%s",s);
				if(s[0]=='*')
					a[i][j]=1;
				else a[i][j]=0;
			}
		}
		dp[0][0]=1;

		for(i=0;i<n;i++)
			dp[0][0]*=2; 


		for(i=0;i<n;i++)
		{
			for(j=0;j<=i;j++)
			{
				if(a[i][j]) //遇到钉子
				{
					dp[i+1][j] += dp[i][j]>>1;
					dp[i+1][j+1] += dp[i][j]>>1;
				}//没遇到
				else dp[i+2][j+1] += dp[i][j];
			}
		}
		ans1=dp[n][m];
		ans2=0;

		for(i=0;i<=n;i++) 
			ans2+=dp[n][i];
		k=gcd(ans1,ans2);
		if(ans1==0)
		{
			ans2=1;k=1;
		}
		printf("%I64d/%I64d\n",ans1/k,ans2/k);
	}
	return 0;
}




内容概要:本文介绍了一种基于蒙特卡洛模拟和拉格朗日优化方法的电动汽车充电站有序充电调度策略,重点针对分时电价机制下的分散式优化问题。通过Matlab代码实现,构建了考虑用户充电需求、电网负荷平衡及电价波动的数学模【电动汽车充电站有序充电调度的分散式优化】基于蒙特卡诺和拉格朗日的电动汽车优化调度(分时电价调度)(Matlab代码实现)型,采用拉格朗日乘子法处理约束条件,结合蒙特卡洛方法模拟大量电动汽车的随机充电行为,实现对充电功率和时间的优化分配,旨在降低用户充电成本、平抑电网峰谷差并提升充电站运营效率。该方法体现了智能优化算法在电力系统调度中的实际应用价值。; 适合人群:具备一定电力系统基础知识和Matlab编程能力的研究生、科研人员及从事新能源汽车、智能电网相关领域的工程技术人员。; 使用场景及目标:①研究电动汽车有序充电调度策略的设计与仿真;②学习蒙特卡洛模拟与拉格朗日优化在能源系统中的联合应用;③掌握基于分时电价的需求响应优化建模方法;④为微电网、充电站运营管理提供技术支持和决策参考。; 阅读建议:建议读者结合Matlab代码深入理解算法实现细节,重点关注目标函数构建、约束条件处理及优化求解过程,可尝试调整参数设置以观察不同场景下的调度效果,进一步拓展至多目标优化或多类型负荷协调调度的研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值