网站的导航栏淄博网站建设招聘
news/
2025/9/23 21:07:48/
文章来源:
网站的导航栏,淄博网站建设招聘,创业网站建设方案项目书,太仓建设网站#xff08;7#xff09;积木画
题目#xff1a;
小明最近迷上了积木画, 有这么两种类型的积木, 分别为 #xfffd;I 型#xff08;大小为 2 个单位面积) 和 #xfffd;L 型 (大小为 3 个单位面积): 同时, 小明有一块面积大小为 2#xfffd;2N 的画布, 画布由 27积木画
题目
小明最近迷上了积木画, 有这么两种类型的积木, 分别为 I 型大小为 2 个单位面积) 和 L 型 (大小为 3 个单位面积): 同时, 小明有一块面积大小为 2×2×N 的画布, 画布由 2×2×N 个 1×11×1 区域构 成。小明需要用以上两种积木将画布拼满, 他想知道总共有多少种不同的方式? 积木可以任意旋转, 且画布的方向固定。
输入格式
输入一个整数 N表示画布大小。
输出格式
输出一个整数表示答案。由于答案可能很大所以输出其对 1000000007 取模后的值。
样例输入
3样例输出
5样例说明
五种情况如下图所示颜色只是为了标识不同的积木 评测用例规模与约定
对于所有测试用例1≤≤100000001≤N≤10000000. 笔记
这道题是一道dp的题目首先我们要找到状态转移的思路这里我们可以从下标为0开始向前找每一个下表对应的组合数
i 0只有I型竖放。
i 1可以将两条I型竖放或者横放。
i 3:可以三个I型竖放 两I型横放一I型竖放 两个L型交叉
我们可以发现L型只会影响两个格所以我们就假设从第三个个字开始进行状态转移我们可以发现第三个格子存在三种情况第一种两个格子都为空第二种上格子为空 第三种下格子为空然后我们对着三种情况进行分析
1dp[i][3] dp[i - 1][3] dp[i - 1][2] dp[i - 1][1] dp[i - 2][3]
这里我当时就有一个疑问问什么要加上dp[i - 2][3]呢我们会发现这种情况是有两者不同的方式她的两种方式包含了dp[i - 1][3]的组合1、当两条I型竖放的时候也就被dp[i - 1][3]包含了当两条横放的时候就是为考虑到的情况所以要加上这种情况。
2dp[i][2] dp[i - 2][3] dp[i - 1][1]:
这两种情况就是在i- 2后加上一个L型 i- 2处一个L型i- 1处一个横放的I型。
3dp[i][1] dp[i -2][3] dp[i - 1][2]:
跟第二种情况相似
明确了dp数组的含义接下来看初始化
由于是求组合数所以我们要将dp[0][0]置为1然后后面的就根据情况来看dp[0][1]与dp[0][2]为0
dp[0][3]为1个I型竖放dp[1][1]与dp[1][2]都为1dp[1][3]为两I型竖放两I型横放。dp[1][3] 2.
接下来求状态转移方程
也就是上面分析的那样
1dp[i][3] dp[i - 1][3] dp[i - 1][2] dp[i - 1][1] dp[i - 2][3]
2dp[i][2] dp[i - 2][3] dp[i - 1][1]:
3dp[i][1] dp[i -2][3] dp[i - 1][2]:
接下来是遍历顺序
我们直接从第三个格子开始遍历在每个循环中分别求出三种情况的dp数组。
下面是完整的AC代码
#includebits/stdc.h
using namespace std;
const long long mod 1e9 7;
int main(){long long n;cin n;long long dp[3][4] {0};dp[0][3] 1;dp[1][3] 2;dp[1][1] 1;dp[1][2] 1;for(long long i 2; i n; i){dp[i % 3][3] (dp[(i - 1) % 3][3] dp[(i - 1) % 3][1] dp[(i - 1) % 3][2] dp[(i - 2) % 3][3]) % mod;dp[i % 3][1] (dp[(i - 2) % 3][3] dp[(i - 1) % 3][2]) % mod;dp[i % 3][2] (dp[(i - 2) % 3][3] dp[(i - 1) % 3][1]) % mod;}cout dp[(n - 1) % 3][3] endl;return 0;
}
9李白打酒加强版
题目
问题描述
话说大诗人李白, 一生好饮。幸好他从不开车。
一天, 他提着酒显, 从家里出来, 酒显中有酒 2 斗。他边走边唱: 无事街上走提显去打酒。 逢店加一倍, 遇花喝一斗。 这一路上, 他一共遇到店 N 次, 遇到花 M 次。已知最后一次遇到的是花, 他正好把酒喝光了。
请你计算李白这一路遇到店和花的顺序, 有多少种不同的可能?
注意: 显里没酒 ( 0 斗) 时遇店是合法的, 加倍后还是没酒; 但是没酒时遇 花是不合法的。
输入格式
第一行包含两个整数 N 和 M.
输出格式
输出一个整数表示答案。由于答案可能很大输出模 1000000007 的结果.
样例输入
5 10样例输出
14样例说明
如果我们用 0 代表遇到花1 代表遇到店14 种顺序如下
010101101000000
010110010010000
011000110010000
100010110010000
011001000110000
100011000110000
100100010110000
010110100000100
011001001000100
100011001000100
100100011000100
011010000010100
100100100010100
101000001010100
评测用例规模与约定
对于 40%40% 的评测用例: 1≤,≤101≤N,M≤10 。
对于 100%100% 的评测用例: 1≤,≤1001≤N,M≤100 。
笔记
还是一道动态规划的题目不过是维数比较高的
确定dp数组含义
dp[i][j][k]:到达经过i个酒店和j个花还剩k斗酒的组合数。
初始化
dp[0][0][2] 1,dp[0][0][0] 1;
状态转移方程
dp[i][j][k] ----- dp[i - 1][j][k / 2] dp[i][j - 1][k - 1]
到这里我们可以想到到达经过了i个酒店j个花还剩k斗酒的时候我们要存放的数据不单单只有组合数还有是否能到达该点所以我们进行特殊判断
对当前的k只进行判断如果k值 % 2 0 并且i 1即上一个经过的地点可以使酒店如果k值 1并且 j 1的话上一个经过的地点就可以是花。由于状态转移方程是dp[i][j][k] dp[i - 1][j][k / 2] dp[i][j - 1][k - 1]所以我们要依次进行这两个判断并将其结果加在原dp[i][j][k]上。
接下来是遍历顺序由于最后一次遇到的是花所以花的遍历一定是在店的遍历之后这样我们才能保证最后一次到的地方是花。
遇到的问题
1为什么最后的结果非要是dp[n][m - 1][1]而不能是dp[n][m][0]呢
我们要求的正是dp[n][m-1][1]这个状态,表示遇到n次店、m-1次花、剩余1斗酒的方案数。这个状态符合题目最后一次遇到的是花,他正好把酒喝光了的要求。
2为什么将下面这句代码放在main函数内部就不能正常运行了int n, m, f\[N\]\[N\]\[N\]
在 C 中局部变量存储在栈上。栈的大小是有限制的如果你定义的数组太大就会超出栈的容量从而导致栈溢出。将该数组声明改为全局变量。
#includebits/stdc.h
using namespace std;
const int mod 1e9 7;
int dp[150][150][150] {0};// 这里对酒的范围化为了m是因为假设一个店都没有经过那么我们要经过m个花所以要消耗m斗酒
int main(){int m,n;cin n m;dp[0][0][2] 1;for(int i 0; i n; i){for(int j 0; j m - 1; j){for(int k 0; k m; k){if(i 1 k % 2 0){dp[i][j][k] dp[i - 1][j][k / 2];}if(j 1 k 1){dp[i][j][k] dp[i][j - 1][k 1];}dp[i][j][k] dp[i][j][k] % mod;}}} cout dp[n][m - 1][1] endl;return 0;
}
10砍竹子
题目
问题描述
这天, 小明在砍竹子, 他面前有 n 棵竹子排成一排, 一开始第 i 棵竹子的 高度为 ℎhi.
他觉得一棵一棵砍太慢了, 决定使用魔法来砍竹子。魔法可以对连续的一 段相同高度的竹子使用, 假设这一段竹子的高度为 H, 那么
用一次魔法可以 把这一段竹子的高度都变为 ⌊⌊2⌋1⌋⌊⌊2H⌋1⌋, 其中 ⌊⌋⌊x⌋ 表示对 x 向下取整。小明想 知道他最少使用多少次魔法可
让所有的竹子的高度都变为 1 。
输入格式
第一行为一个正整数 n, 表示竹子的棵数。
第二行共 n 个空格分开的正整数 ℎhi, 表示每棵竹子的高度。
输出格式
一个整数表示答案。
样例输入
6
2 1 4 2 6 7样例输出
5样例说明
其中一种方案
21426214267→214262→214222→211222→111222→111111→214262→214222→211222→111222→111111共需要 5 步完成
笔记
先来分析者道题目我们每次选取最高的那一棵竹子进行处理如果周围只有他一根高度的那么就只处理这一根如果周围有连续的竹子一样高就可以一起处理。由于每次都是处理高度最大的元素所以我们可以用优先队列来处理因为我们需要记录竹子的高度以及判断竹子的编号是否连续所以我们就需要设置优先队列元素的类型为pair类型ll,int:
注意一点这里我们安排的顺序也是有考究的当我们的两棵竹子高度相同时优先队列就会判断second元素以second元素为标准再次排出顺序。所以我们要将first设置为高度second设置为编号这样我们在处理连续编号进行index -- 遍历的时候就可以进行判断是否连续。
所以这道题就是模拟加优先队列首先向队列中加入元素如果元素不是1就直接加入接着我们用一个while循环来处理队列中的元素将队首元素取出并分别赋值将队首元素弹出后我们对该元素进行处理如果处理后的高度不为1就将处理后的元素加入队列接着从当前标记开始我们从队列中取出新的对首元素判断是否高度相同且连续。处理为依次队列元素后count。
#include iostream
#include queue
#include cmath
using namespace std;typedef long long ll;priority_queuepairll, int bam;int main() {int count 0;int n;cin n;for (int i 0; i n; i) {ll h;cin h;if(h ! 1){bam.push(make_pair(h, i));}}while (!bam.empty()) {ll H bam.top().first;int index bam.top().second;bam.pop();ll h1 sqrtl(H / 2 1);if (h1 ! 1) {bam.push(make_pair(h1, index));}while (!bam.empty() bam.top().second index - 1 bam.top().first H) {bam.pop();index--;if (h1 ! 1) {bam.push(make_pair(h1, index));}}count;}cout count endl;return 0;
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/913887.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!