西南交通大学算法分析与实验7.4——迭代法/动态规划思想

样例结果分析:

10 = 9 +1

10 = 8 + 2

10 = 7 + 3

10 = 7 + 2  + 1

10 = 6 + 4

10 = 6 + 3 + 1

10 = 5 + 4 + 1

10 = 5 + 3 + 2

10 = 4 + 3 + 2 +1

当然本题可以使用回溯法解决且难度并不是很大,只需要注意剪枝即可。下面介绍使用迭代法解决的方法。我看到这题的时候首先想到的是使用动态规划解决,但后面发现其实也像一个迭代的过程。主要是它只用前一个状态便可以得出现状态。

因为N >= 3,显然N= 3 时:只有一种搭建放方法:

210

现在N = 4,意味着多了一块积木,我们可以有三种选择:

放在第一层、第二层、或者他单独成为一层,即下面的情况:

310
220
211

显然后两种都不满足不出现相同砖数的要求,故舍去。

故N = 4的时候

310

N = 5时又多了一块积木,这时候我们还要N = 3的基础上进行操作吗?显然不用,同样的思路,我们针对N = 4 时的台阶采用同样的方法,添加一块积木——可以是第一层、第二层添加一层可以得到下面的表

410
320
311

最后一种情况不符合故舍去。

N = 5:

410
320

同理N = 6时:

510
420
411
420
330
321

这时出现了相同的结果,第一种组合的第2层加1 和 第二种组合的第1层加1得到的结果是相同的,因此这里需要一个去重的操作,此外我们还可以看到第一次出现了单独作为一层的情况

321

为了重复上面的相同的操作,我们必须得在后面在添加一个0,这样就能与上面的方法保持一致了即:

3210

N  = 6 且去重之后的结果:

510/
420/
3210

继续迭代这个过程到N即可。

#include<iostream>
#include<vector>

using namespace std;

bool compare_ans(vector<int>num, vector<vector<int>>Ans) { // 判断是否已经有这个解
	for (int i = 0; i < Ans.size(); i++) {
		vector<int>temp = Ans[i];
		if (num == temp) {
			return false;
		}
	}
	return true;
}
int main() {
	//当前的状态只与n-1 的状态有关,用两个2维数组即可存储。
    //temp 表示n -1,ans 表示n;
	vector<vector<int>>temp;
	vector<vector<int>>ans;
	int n;
	cin >> n;
	ans.push_back({ 2,1,0});//初始化
	for (int i = 0; i < n - 3; i++) {
		temp = ans;
		ans.clear();
		for (int j = 0; j < temp.size(); j++) {
			for (int k = 0; k < temp[j].size(); k++) {
				vector<int>num;
				num = temp[j];
				num[k]++;
				if (k == 0) {
					bool judge = compare_ans(num, ans);
					if (judge == 1) {
						ans.push_back(num);
					}
					continue;
				}
				if (k == temp[j].size()-1) {
					if (num[k] < num[k - 1]) {
						//末尾舔0再进行判重
							num.push_back(0);
							bool judge = compare_ans(num, ans);
							if(judge == 1){
							ans.push_back(num);
						}
						continue;
					}
				}
				if (num[k] < num[k - 1]) {
					bool judge = compare_ans(num,ans);
					if (judge == 1) {
						ans.push_back(num);
					}
					continue;
				}
			}
		}
	}
	cout << ans.size();
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亏贼的baby

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值