IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> XTU1378Blocks -> 正文阅读

[C++知识库]XTU1378Blocks

dp题光看代码可能比较抽象(本菜鸡是这样的),所以我讲的略小白一点,大佬就别看了orz

题目描述

给你一个n块积木,每个积木块都是立方体,现在把它们排列一排,成m列,要求每列上至少有1个积木,且从左到右,每列的积木数量呈严格单调下降。比如8块积木,排成3列,那么合法的安排方案为521或者431。请问n块积木按规则排成m有多少种不同的方案?

输入

第一行是一个整数T(1≤T≤1000),表示样例的个数。

以后每个样例占一行,为两个整数?n(1≤n≤100),m(1≤m≤10)。

输出

依次每行输出一个样例的结果,为一个整数。

样例输入

2
8 3
13 4

样例输出

2
3

样例解释

第二个样例的合法方案为7321,6421,5431

先不多说,我喜欢先放代码。代码略丑(见谅)

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<bits/stdc++.h>
using namespace std;

int main() {
	int t;
	int i, j, k, l, n, m,sum;
	scanf("%d", &t);
	while (t--) {
		int a[101][11][110];//a[i][j][k]为i块积木,共j列,第一列为k个方块的方案数
		memset(a, 0, sizeof(a));
		a[1][1][1] = 1;
		scanf("%d %d", &n, &m);
		for (i = 2; i <= n; i++) {
			for (j = 1; j <= m; j++) {
				for (k = 1; k <= i; k++) {
					if (i == k && j == 1) { //如果排成一列,第一列为总积木时,只有一种情况 
						a[i][j][k] = 1;
					} else {
						for (l = k - 1; l >= 1; l--) {
							a[i][j][k] += a[i - k][j - 1][l];
						}
					}
				}
			}//排几列
		}
		sum = 0;
		for (i = 1; i <= n; i++) {
			sum += a[n][m][i];
		}
		printf("%d\n", sum);
	}
	return 0;
}

举个栗子(手动dp):

有6个积木,要排3列,sum=a[6][3][1]+a[6][3][2]+a[6][3][3]+...a[6][3][6]

而a[6][3][2]=a[4][2][1],a[4][2][1]=a[3][1][0]=0

a[6][3][3]=a[3][2][1]+a[3][2][2],a[3][2][2]=a[1][1][1]=1

a[6][3][4]=a[2][2][1]+a[2][2][2]+a[2][2][3],a[2][2][1]=a[1][1][0]=0

...后面的更不可能了

这个搭建过程:先搭第一列,第一列数字确定下来之后,sum=第二列的情况(记得把总积木和列数都要减去相应的),即第二列分别为1,2,3...n-第一列的积木。

而第二列的每一种的情况又分别=第三列的情况...

这样一直继续下去,就是一个dp过程。

可以总结出方程a[i][j][k]=a[i-k][j-1][1]..........+a[i-k][j-1][k-1]

这里的k是可以优化的,上面的栗子中可以看见,有一些k完全是不可能存在的,都已经超过总积木,或者有些列已经为0了,具体优化留给你们想叭。

代码思想:

确定下核心方程之后,就是依次枚举i,j,k,因为dp的终点我们应该是确定的,就是排成一列,第一列就是总积木时,这时的情况是1。而其他情况都可以用方程运算。

这边可以把整个搭建过程放到while函数的外面,再输入输出,这样代码会更好看啦(但是我懒)。

如果还是有点晕的欢迎留言讨论,然后要是说错了欢迎大佬捉虫QwQ

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-08 13:48:12  更:2022-01-08 13:50:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:05:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码