【算法每日一练]-动态规划(保姆级教程 篇14) #三倍经验 #散步 #异或和 #抽奖概率

目录

 今日知识点:

金字塔的正反dp两种方案,转移方程取决于dp的具体含义

取模实现循环走m步回到原点的方案

在统计上升子序列的时候使用最小结尾元素进行标记,一举两得

将亏本的概率转换各种情况的方案,然后统计亏本的情况的方案数烦求概率

三倍经验

散步

 异或和

抽奖概率 


三倍经验

思路:

首先不要考虑那么复杂,如果只是取数,但不考虑加倍的操作,那么就简单很多,只需要从下层想上层推导即可。保证每此都是最优解就行了。

这个时候f[i][j]从f[i-1][j]和f[i-1][j-1]中来。那么自然:

f[i][j]=max(f[i-1][j],f[i-1][j-1]) +a[i][j]。

然后我们再考虑要成3倍的情况,因为每个点可以对应是否有3倍的情况,而且这个消耗情况也要记录下来。所以需要开三维来表示。

设置f[i][j][k]表示在耗费次3倍操作下 且走到i,j对应的最优解。
 转移方程:

 f[i][j][l]=max(f[i-1][j][l],f[i-1][j-1][l])+a[i][j]; (当前数没有消耗次数)

 f[i][j][l]=max(f[i][j][l],max(f[i-1][j][l-1],f[i-1][j-1][l-1])+a[i][j]*3(当前数消耗次数了)
  最终需要在f[n][i][0~k]中找答案

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=105,INF=-3e9;
int n,k;
ll a[N][N],f[N][N][N],ans=INF;
int main(){cin>>n>>k;for(int i=1;i<=n;i++)for(int j=0;j<=n;j++)for(int l=0;l<=k;l++)f[i][j][l]=INF;for(int i=1;i<=n;i++)for(int j=1;j<=i;j++){cin>>a[i][j];for(int l=0;l<=min(k,i);l++){if(l==0)f[i][j][l]=max(f[i-1][j][l],f[i-1][j-1][l])+a[i][j];else{f[i][j][l]=max(f[i-1][j][l],f[i-1][j-1][l])+a[i][j];f[i][j][l]=max(f[i][j][l],max(f[i-1][j][l-1],f[i-1][j-1][l-1])+a[i][j]*3);}}}for(int i=1;i<=n;i++)for(int l=0;l<=min(k,n);l++)ans=max(ans,f[n][i][l]);cout<<ans;
}

上面的是正向写法(也就是从上到下)。

当然也可以从下到上写:

 设置f[i][j][k]表示从i,j从开始消耗k次对应的最优解。

那么f[i-1][j-1]和f[i-1][j]就应该借此更新:(然后再拆成是否乘3倍,那就是4个式子)

            f[i-1][j-1][k]=max(f[i-1][j-1][k],f[i][j][k]+a[i-1][j-1]);
            f[i-1][j-1][k+1]=max(f[i-1][j-1][k+1],f[i][j][k]+a[i-1][j-1]*3);
            f[i-1][j][k]=max(f[i-1][j][k],f[i][j][k]+a[i-1][j]);
            f[i-1][j][k+1]=max(f[i-1][j][k+1],f[i][j][k]+a[i-1][j]*3);    

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ans=-0x3f3f3f3f,f[110][110][110],a[110][110];
int n,m;
int main(){memset(f,-0x3f3f3f3f,sizeof(f));cin>>n>>m;for(int i=1;i<=n;i++)for(int j=1;j<=i;j++)cin>>a[i][j];for(int i=1;i<=n;i++){f[n][i][0]=a[n][i];f[n][i][1]=a[n][i]*3;}for(int i=n;i>=2;i--)for(int j=1;j<=i;j++)for(int k=0;k<=min(n-i+2,m);k++){f[i-1][j-1][k]=max(f[i-1][j-1][k],f[i][j][k]+a[i-1][j-1]);f[i-1][j-1][k+1]=max(f[i-1][j-1][k+1],f[i][j][k]+a[i-1][j-1]*3);f[i-1][j][k]=max(f[i-1][j][k],f[i][j][k]+a[i-1][j]);f[i-1][j][k+1]=max(f[i-1][j][k+1],f[i][j][k]+a[i-1][j]*3);	}for(int i=0;i<=min(n,m);i++){ans=max(f[1][1][i],ans);}cout<<ans;
}

 可以会有人有疑问:既然(i,j)可以到(i+1,j)和(i+1,j+1),为什么不是f[i][j]=max(f[i+1][j],f[i+1][j+1])这个式子呢?

上图是正确的更新路线,举个例子:f[3][2]只能被f[2][1]和f[2][2]更新,因为只有这两个点才能到f[3][2],所有才有了f[i][j]=max(f[i-1][j],f[i-1][j-1])这个式子。 

OK解释完了!

        

        

散步

思路:

 设置dp[i][j]表示已经走了i步,然后到达j。然后循环可以用取模实现,但是取模一定是0~n-1,所以需要进行映射。

转移方程:dp[i][j]=dp[i-1][(j+1)%n]+dp[i-1][(j-1+n)%n]

最终dp[m][0]就是答案。

#include <bits/stdc++.h>
using namespace std;
int dp[35][35],n,m;
int main(){cin>>n>>m;dp[0][0]=1;for(int i=1;i<=m;i++)for(int j=0;j<n;j++)dp[i][j]=dp[i-1][(j+1)%n]+dp[i-1][(j-1+n)%n];cout<<dp[m][0];
}

        

         

 异或和

给一个长n的序列a1,a2……an,寻找在a的所有递增子序列(可以为空)的异或和中出现的数。

输入:                    输出:

2                                 4

1 5                              0 1 4 5

思路:

题意就是统计异或和,不过是仅统计所有上升子序列的异或和,那么就在每次更新上升子序列的时候就打一次标记,用什么打标记,当然直接使用数组元素最方便。
所以:设置dp[i]表示异或和为i的满足题意的最小结尾元素。(里面存的是最小的结尾元素)
dp[j]<a[i]时候(i可以拼在j后面):更新dp[j^a[i]]=min(dp[j^a[i],a[i])(标记了那个新异或和出现了)
最后统计有哪些dp被使用过,就说明这些数是答案
 

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,a[N],dp[N];int main(){memset(dp,0x3f3f3f3f,sizeof(dp));dp[0]=0;cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++)for(int j=0;j<=550;j++)if(dp[j]<a[i]) dp[j^a[i]]=min(dp[j^a[i]],a[i]);vector<int> ans;for(int i=0;i<=550;i++)if(dp[i]!=0x3f3f3f3f) ans.push_back(i);cout<<ans.size()<<'\n';for(int i:ans)cout<<i<<" ";}

        

        

抽奖概率 

有一个抽奖活动:抽一个2元,可能会抽出1,2,3,4元(概率相等)。

问抽n次,亏本的概率是多少(奖金小于本金)?纯赚超过一半本金的概率是多少

输入:2           输出:3/16(分数时候输出最简分数)

                                   3/16

思路:

直接求概率不太容易。而且还要最简分数,那么就转化乘求方案数就会具体很多。

设置dp[i][j]表示已经抽奖i次且拿到了总额为j的方案数.dp[i][j]=dp[i-1][j-1,2,3,4]即可。

最后的最简分数可以使用gcd函数完成。
 

#include <bits/stdc++.h>
using namespace std;
int dp[40][160],n;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}int main(){cin>>n;dp[1][1]=dp[1][2]=dp[1][3]=dp[1][4]=1;for(int i=1;i<=n;i++)for(int j=i;j<=4*n;j++){for(int k=1;k<=4;k++)if(j>k) dp[i][j]+=dp[i-1][j-k];}int sum1=0,sum2=0,sum=1;for(int i=n;i<2*n;i++)sum1+=dp[n][i];for(int i=3*n+1;i<=4*n;i++)sum2+=dp[n][i];for(int i=1;i<=n;i++)sum*=4;int k=gcd(sum1,sum);cout<<sum1/k<<"/"<<sum/k<<'\n';k=gcd(sum2,sum);cout<<sum2/k<<"/"<<sum/k<<'\n';}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/321489.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

独立看门狗与窗口看门狗

一、简介 STM32F10xxx内置两个看门狗&#xff0c;提供了更高的安全性、时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障&#xff1b;当计数器达到给定的超时值时&#xff0c;触发一个中断(仅适用于窗口型看门狗)或产…

基于SpringBoot的在线考试系统源码和论文

网络的广泛应用给生活带来了十分的便利。所以把在线考试管理与现在网络相结合&#xff0c;利用java技术建设在线考试系统&#xff0c;实现在线考试的信息化管理。则对于进一步提高在线考试管理发展&#xff0c;丰富在线考试管理经验能起到不少的促进作用。 在线考试系统能够通…

P10 RV1126推流项目——ffmpeg输出参数初始化

前言 从本章开始我们将要学习嵌入式音视频的学习了 &#xff0c;使用的瑞芯微的开发板 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《Linux C应用编程&#xff08;概念类&#xff09;_C…

centos安装人大金仓数据库

1&#xff0c;人大金仓官网下载安装包 下载链接https://www.kingbase.com.cn/xzzx/index.htm 下载这个版本&#xff0c;数据库授权文件下载下面的这个 2&#xff0c;点击下载的软件版本&#xff0c;挂载iso 点击CDROM中运行setup.sh,用普通用户进行运行 sh setup.sh 一直点…

Oracle导出CSV文件

利用spool spool基本格式&#xff1a; spool 路径文件名 select col1||,||col2||,||col3||,||col4 from tablename; spool off spool常用的设置&#xff1a; set colsep ;    //域输出分隔符 set echo off;    //显示start启动的脚本中的每个sql命令&#xff0c;缺…

数论:数论分块

第一种情况&#xff1a;求 如果暴力算法是O(n)的复杂度&#xff0c;而整除分块则将复杂度减低到O() 对于这种情况有两条重要的性质: 1.分块的块数最多为&#xff1a; 2.第i个数所在块的右端点为&#xff1a; 只需要进行分类前缀和即可 int ans 0; for (int l 1, r; l …

GitHub项目推荐:IDE-3D

项目地址 GitHub - MrTornado24/IDE-3D: [SIGGRAPH Asia 2022] IDE-3D: Interactive Disentangled Editing For High-Resolution 3D-aware Portrait Synthesisx 项目简述 这是一个交互式的3D画图工具。无论是改图还是成图&#xff0c;都能使用。是一个很有意思的项目。 项目…

Linux-进程间通信_管道

项目场景&#xff1a; 须熟知文件管理和进程方面的基础知识 通过Xshell和VScode 相互进行远程开发&#xff0c;学习进程间通信的其中一种方式——管道。 问题描述 依照我们曾经所学的知识&#xff0c;我们仅仅只能在单个进程中进行数据的交互&#xff0c;但是在实际应用中&a…

【DevOps-03】Build阶段-Maven安装配置

一、简要说明 下载安装JDK8下载安装Maven二、复制准备一台虚拟机 1、VM虚拟复制克隆一台机器 2、启动刚克隆的虚拟机,修改IP地址 刚刚克隆的虚拟机 ,IP地址和原虚拟的IP地址是一样的,需要修改克隆后的虚拟机IP地址,以免IP地址冲突。 # 编辑修改IP地址 $ vi /etc/sysconfig…

动态分区分配算法-第四十四天

目录 前言 首次适应算法&#xff08;First Fit&#xff09; 最佳适应算法&#xff08;Best Fit&#xff09; 最坏适应算法&#xff08;Worst Fit&#xff09; 临近适应算法&#xff08;Next Fit&#xff09; 本节思维导图 前言 动态分区分配算法&#xff1a;在动态分区分…

基于EMD-SpEn(样本熵)联合小波阈值去噪

代码原理 基于 EMD-SpEn&#xff08;样本熵&#xff09;联合小波阈值去噪方法是一种用于信号降噪的信号处理方法&#xff0c;它结合了经验模态分解 (EMD)、样本熵 (SpEn) 和小波阈值处理技术。 首先&#xff0c;使用 EMD 将原始信号分解为一组称为经验模态函数 (IMFs) 的信号…

华为云CES监控与飞书通知

华为云负载均衡连接数监控与飞书通知 在云服务的日常运维中&#xff0c;持续监控资源状态是保障系统稳定性的关键步骤之一。本文通过一个实际案例展示了如何使用华为云的Go SDK获取负载均衡器的连接数&#xff0c;并通过飞书Webhook发送通知到团队群组&#xff0c;以便运维人员…