首页 > 其他分享 >2023年11月第一周第二次总结

2023年11月第一周第二次总结

时间:2023-11-05 19:11:19浏览次数:40  
标签:11 count 第一周 int long 骨牌 2023 长度 dp

1. 动态规划

在我看来动态规划就是用一种缓存机制来保存之前求解的答案,如果要再次用到已经求解过的答案就直接把缓存里面的答案给他而不必再次求解,也就是用空间换取时间

那么要解决动态规划问题,最好按照以下步骤来求解

      1. 用暴力递归来求解问题
      2. 能用记忆化搜索就先用记忆化搜索来优化递归,时间复杂度是O(N)
      3. 用状态转移方程来解决问题

解题思路

字有点丑,见谅。

解题方法

暴力递归

//纯暴力递归 
#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#define N 51//数组的最大长度 
long long count;//用来计数方案 
void f(int n);//n代表长方形长度 

int main(int argc, char* argv[])
{
    int n;//输入长方形的长度 
    long long res[N];//存放结果 
    int m = 0;//记录结果的个数 

    while(~scanf("%d", &n));
    {
        count = 0;//每次初始化计数为0 
        f(n);//递归求方案数 
        res[m++] = count;//把求得的结果放在结果数组保存起来 
    }

    //打印结果 
    for (int i = 0; i < m; i++)
    {
        printf("%lld\n", res[i]);
    }

    return 0;
}
void f(int n)
{
    if (n == 0)//如果长方形的长度为0,代表已经把长方形铺满了,方案数加1 
    {
        count++;
        return;//结束递归,回到上一次递归调用 
    }

    if (n >= 3)//如果长度大于等于3,就可以铺三种骨牌,即铺长度为1*3的骨牌、1*2的骨牌、1*1的骨牌 
    {
        f(n - 3);//铺1*3的骨牌,所以长度减3 
        f(n - 2);//铺1*2的骨牌,所以长度减2 
        f(n - 1);//铺1*1的骨牌,所以长度减1 
    } 
    else if (n == 1){//如果长度为1,就只能铺长度为1*1的骨牌 
        f(n - 1);
    }
    else {//如果长度为2,那么就可以铺1*2的骨牌和1*1的骨牌 
        f(n - 2);//铺1*2的骨牌,所以长度减2
        f(n - 1) ;//铺1*1的骨牌,所以长度减1 
    }
    return ;//可以省略 
}

记忆化搜索

//记忆化搜索 
#include <stdio.h>
#include <string.h>
#define N 100

long long dp[N];//用来记录已经算出来的答案 

long long f(int n)//n代表长方形的长度 
{
    if (dp[n] != -1)  {//表示答案已经在我的缓存表里直接返回结果 
    	return dp[n];
	} 
	
	long long int count = 0;//用来统计有多少个方案数 
	
	if (n == 0) {//如果长方形的长度为0,代表已经把长方形铺满了,返回1 
		return 1;
	}
	
	if (n >= 3)  {//如果长度大于等于3,就可以铺三种骨牌,即铺长度为1*3的骨牌、1*2的骨牌、1*1的骨牌 
		count += f(n - 3);//加上铺1*3的骨牌的方案数 
		count += f(n - 2);//加上铺1*2的骨牌的方案数
		count += f(n - 1);//加上铺1*1的骨牌的方案数
	}
	else if (n >= 2) {//如果长度为2,那么就可以铺1*2的骨牌和1*1的骨牌
		count += f(n - 2);//加上铺1*2的骨牌的方案数
		count += f(n - 1);//加上铺1*1的骨牌的方案数
	}
	else {//如果长度为1,就只能铺长度为1*1的骨牌
		count += f(n - 1);//加上铺1*1的骨牌的方案数
	}
	
	dp[n] = count;//把求出来的答案保存到我的缓存表里面 
	
	return count;//返回方案数 
}

int main(int argc, char* argv[])
{
    int n;//表示长方形的长度 
    long long res[N];//存放结果 
    int m = 0;//记录结果的个数 
    
    //注意这个函数要在c++才能使用 
    memset(dp, -1, sizeof(dp));//初始化dp数组让每个元素初始化为-1,-1表示答案没有求出来
    
    while (scanf("%d", &n) == 1)
    {
        res[m++] = f(n);//把结果保存起来 
    }

	//打印结果 
    for (int i = 0; i < m; i++)
    {
        printf("%lld\n", res[i]);
    }
    
    return 0;
}

动态规划

//动态规划 
#include <stdio.h>
#include <string.h>
#define N 100

long long dp[N];//dp数组用来记录之前的结果 

void solve()
{
    //通过暴力递归的出来的
    dp[0] = 1;
    dp[1] = 1;
    dp[2] = 2;

	/*
	对于每个 n,铺法数量等于前三个位置的铺法数量之和。这是由于对于 n 个位置的地板,我们可以在最后一个位置放置一块 1 x 1 的砖块,或者在最后两个位置放置一块 2 x 1 的砖块,或者在最后三个位置放置一块 3 x 1 的砖块。因此,铺法数量等于这三种情况下的铺法数量之和
	*/

    for (int i = 3; i < N; i++)//数组的下标表示 n 的取值,dp[i] 表示当 n = i 时的铺法数量。
    {
        dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];
    }
}

int main()
{
    int n;
    long long res[N];//存放结果 
    int m = 0;//记录结果的个数 

    memset(dp, 0, sizeof(dp));
    solve();//求出所有的结果 

    while (scanf("%d", &n) == 1)
    {
        res[m++] = dp[n];//把结果存起来 
    }

	//打印结果 
    for (int i = 0; i < m; i++)
    {
        printf("%lld\n", res[i]);
    }

    return 0;
}

总结

对于动态规划的题目,建议先尝试写出来它暴力递归的解法,在来尝试找到状态转移方程,来求解出动态规划的题目。

标签:11,count,第一周,int,long,骨牌,2023,长度,dp
From: https://www.cnblogs.com/lwj1239/p/17810896.html

相关文章

  • 11月3日前端需要学习的知识、自闭合标签、meta标签、div标签
    目录前端需要学习的知识生成的网页类型静态网页动态网页网页的架构c/s架构b/s架构浏览器的特别用法第一种结合python来使用第二种将文件拖入浏览器里面(这就符合渲染了)重点HTML首先!DOCTYPEhtml其次就是html到/html还有就是head到/head的内部最后就是body到/body总结其它的标签......
  • 鹏城杯2023初赛 pwn(未完)
    silent打开ida一看,没有输出函数,只有一个栈溢出。跟巅峰极客的linkmap有点像,都是没有输出函数而且fullrelro,没法打ret2dl_resolve但是linkmap那道题中是有能函数能将地址放到bss上的,所以它可以把read的地址放到bss上,然后通过修改bss上的read地址,加上栈迁移来执行别的内容。而这......
  • CSP-S2023总结
    CSP-S2023总结T1简单模拟,我因为对题目的理解错误丢了分,这是很不应该的。T2DP,我因为对dp不太熟练,同时对题意同样理解有误,导致暴力分只有10分。T3大模拟,我在看题之后并没有计划在这上面花太多时间,再加上T1,T2失误导致的时间紧张,我没有在这题上得分。T4算是思维题,我没有对它进行充......
  • CF1196B
    题意:n个数,分割成k个部分,使得每份和都为奇数做法:一个序列的和的奇偶性和偶数没关系,所以只需要考虑奇数的个数现在考虑两个问题:1.如果奇数的个数小于最终要求的k,那么就无法完成分类(即是如果一个数一块也不行)2.如果奇数的个数,记为cnt,cnt的奇偶性和k的奇偶性不同,例如cnt为3,k为2......
  • Matlab 2023a图文安装教程及下载
    MATLAB是由美国MathWorks公司出品的专业数学软件,用于算法开发,数据可视化,数据分析以及数值计算的高级技术计算语言和交互式环境,MATLAB是矩阵和实验室两个词的组合,意为矩阵工厂(矩阵实验室),主要包括MATLAB和Simulink两大部分。它将数值分析,矩阵计算,科学数据可视化以及非线性动态系统的......
  • 2023-2024-1 20231303 《计算机基础与程序设计》赵泊瑄第六周学习总结
    2023-2024-120231303《计算机基础与程序设计》赵泊瑄第六周学习总结作业信息这个作业属于哪个课程2023-2024-1-计算机基础与程序设计这个作业要求在哪里作业要求的链接2023-2024-1计算机基础与程序设计第六周作业)这个作业的目标总结第六周学习收获作业正文......
  • 学期:2023-2024-1 学号:20231426 《计算机基础与程序设计》第六周学习总结
    作业信息这个作业属于哪个课程2022-2023-1-计算机基础与程序设计这个作业要求在哪里2022-2023-1计算机基础与程序设计作业这个作业的目标通过教材内容了解复合数据结构、查找与排序算法、递归、代码安全、简单类型与组合类型作业正文https://www.cnblogs.com/......
  • C++11语法——std::move()
    std::move()在C++中,std::move()用于将对象转换为右值引用。关于左值、左值引用、右值、右值引用左值是一个表示数据的表达式(比如变量名或者解引用的指针),程序可以获取其地址传统的C++引用,即是左值引用。C++11新增右值引用,用&&表示。右值是可出现在赋值表达式的右边,但不......
  • android studio 编译Telegram源码经验总结(2023-11-05)
    前言Telegram是一款强大的端到端加密IM,专注于安全性和速度,支持Android/IOS/Windows/macOS等平台,功能丰富,运行流畅,免费开源,代码具有学习和研究意义。一、androidtelegram源码下载地址:github:https://github.com/DrKLO/Telegram.git二、编译环境的选择:Windows版本:1064位;Andro......
  • 2023/11/4
    简单看完翁恺C语言入门后的一些难点经典的素数打印,以及观察改良后的代码,还有构造素数表2023/11/4二进制的补码很关键,理解了它就能理解字节的知识8个字节的二进制数的范围,加了unsigned就非负且乘二了,还加了有形象的图说明超过那个范围就会回环往复,inf表示无穷,nan表示不......