秋招突击——算法打卡——5/31——复习{采药问题、(状态压缩DP)小国王}——新做:{盛最多水的容器、整数转罗马数字}

本文主要是介绍秋招突击——算法打卡——5/31——复习{采药问题、(状态压缩DP)小国王}——新做:{盛最多水的容器、整数转罗马数字},希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 复习
      • 背包模型——采药问题
      • 状态压缩DP——小国王
        • 思路分析
        • 实现代码参考
    • 新作
      • 盛最多的水
        • 个人实现
          • 思路分析
          • 实现代码
        • 参考分析
          • 思路分析
          • 实现思路
      • 整数转罗马数字
        • 个人实现
          • 思路分析
          • 实现代码
        • 参考实现
          • 思路分析
          • 实现代码
    • 总结

复习

背包模型——采药问题

  • 原题链接
  • 这里回忆的时候,还是有点问题,就是起点值怎么写?并不确定!
  • 然后关于这个表达式,也是弄了半天才想起来,还是要多多练习一下!
#include <iostream>
#include <algorithm>using namespace std;
const int T = 1010;
const int M = 110;
int t[M],w[M];
int f[M][T];
int f1[T];
int n,m;int main(){cin>>n>>m;for (int i = 1; i <= m; ++i) {cin>>t[i]>>w[i];}// 遍历所有的药物// f[i][j]:表示在前i个物体下,容量为j的若干种装法中,最高的价值// 集合划分,对于第i个物体而言,也就是两种情况,装或者不装,装f[i-1][j - t[i]] + w[i],不装f[i-1][j]int res = 0;for (int i = 1; i <= m; ++i) {// 什么时候置零是一个问题,不知道怎么办f[i][0] = 0;for (int j = 1; j <= n && t[i] <= j; ++j) {f[i][j] = max(f[i-1][j],f[i -1][j - t[i]] + w[i]);res = max(res ,f[i][j]);}}cout<<res;// 使用滚动矩阵进行优化for (int i = 1; i <= m ; ++i) {for (int j = n; j >=  1 && t[i] <= j; j--) {f1[j] = max(f1[j],f1[j - t[i]] + w[i]);}}cout<<f[n]<< endl;
}
  • 关于二维数组,基本思路是对的,就分两种情况,装或者不装,但是你得分开写
    参考信息
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

状态压缩DP——小国王

  • 题目内容
    在这里插入图片描述
思路分析
  • 参考链接:状态压缩
  • 这道题是真的不会,当时听了半天都没听懂,然后直接跳过了,但是也是dp的一种,经常考,还是要学习一下啊。
  • 这里是使用二进制表示某一个行数的棋盘的状态

在这里插入图片描述

  • 今天是不可能完全搞懂了,就搞懂局部吧,半个小时能懂多少懂多少,不然没时间搞别的东西了。再看一遍,也觉得是昏了头了,即使要是考了这个,直接跳过吧。

  • 第i行的摆放位置,仅仅和第i-1行是有关系的,所以仅仅需要考虑第i-1的状态

  • 第i行可以摆放x中状态,然后在判断一下是否和第i-1行是合法的,然后在进行累加,所以需要干两件事

    • 检查第i行的状态和第i-1行状态是否是合法的
    • 第i行有哪些合法状态
      暂时就分析到这里,明天就是看看代码还有怎么计算预设的状态转换了。 请添加图片描述
      请添加图片描述
实现代码参考
#include <iostream>
#include <vector>using namespace std;typedef long long LL;const int N = 11, M = 1 << N, C = N * N;int n, m, K;
LL f[N][C][M];
int cnt[M];
vector<int> legal_state;
vector<int> state_trans[M];bool check(int state)
{return !(state & state >> 1);
}
int count(int state)
{int res = 0;for (int i = 0; i < n; ++ i) res += state >> i & 1;return res;
}
int main()
{cin >> n >> K;//预处理所有合法状态for (int st = 0; st < 1 << n; ++ st)//检查当前状态是否合法if (check(st))legal_state.push_back(st),cnt[st] = count(st);m = legal_state.size();//预处理所有合法状态的合法转移for (auto cur_st: legal_state)for (auto to_st: legal_state)if (!(cur_st & to_st) && check(cur_st | to_st))//上下不相邻且纵坐标也不相邻state_trans[cur_st].push_back(to_st);//动态规划f[0][0][0] = 1;for (int i = 1; i <= n; ++ i)for (int j = 0; j <= K; ++ j)for (auto &state: legal_state)for (auto &pre_st: state_trans[state])if (j - cnt[state] >= 0)f[i][j][state] += f[i - 1][j - cnt[state]][pre_st];//统计目标状态的所有方案数LL res = 0;for (auto state: legal_state) res += f[n][K][state];cout << res << endl;return 0;
}

作者:一只野生彩色铅笔
链接:https://www.acwing.com/solution/content/56348/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

新作

盛最多的水

题目链接
在这里插入图片描述

个人实现
思路分析
  • 不像是动态规划,最直白的做法是进行暴力搜索的,但是问题空间的达到了10的10次方,有点爆炸,想想看怎么减少,但是就算去掉重复的,也是10的9次方。
  • 对了,这个可以试试看双向指针,两边,哪边移动会变大,就移动哪边,移动之后,在计算一下体积有没有变大
  • 双指针没想清楚,但是后来想清楚了,应该先找到最大值和次大值,然后分别向两边进行遍历,因为很显然,在最大值和次大值中间的数字,任何容积都是比这两个小的。所以只有可能向两边进行遍历。但是这里写的有点慢,就是求第二大的数字的时候,没写好,看看有什么更方便的方式。
  • 这里有个问题
    • 并不知道怎么移动左右指标比较合理!!
实现代码
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;const int N = 100000;
int maxArea(vector<int>& h) {// 定义双指针int first = INT_MIN,second = INT_MIN,firstIdx,secondIdx;for (int i = 0; i < h.size(); ++i) {if (h[i] > first )   first = h[i] , firstIdx = i;if (h[i] > second && h[i] < first )   second = h[i] , secondIdx = i;}int l = min(firstIdx,secondIdx),r = max(firstIdx,secondIdx);int len ,vol = 0;while(l >= 0 || r < h.size()){len = r - l;int temp = min(h[l],h[r]) * len;vol = vol < temp ? temp:vol;// 然后根据情况进行迁移// 关于这里如何移动,并不知道怎么调整if (h[l] < h[l + 1])    l --;if (h[r] < h[r - 1])    r ++;}return vol;
}int main(){vector<int> n = {1,8,6,2,5,4,8,3,7};cout<<maxArea(n)<<endl;
}
参考分析
思路分析
  • 好吧,我想多了,我这样做并不是最优的,是双指针,但是是从两边开始往中间移动的双指针,而且是两个指针进行比较,那个指针的数值比较低,然后移动哪一个?
  • 证明过程比较形象,具体如下:
    • 用反证法,假设一个最优值,然后一边先到达最优值,然后在控制另外一边进行到达,然后反正在移动过程中不存在最优值
实现思路
int maxArea(vector<int>& h) {// 定义双指针int vol = 0,l = 0,r = h.size() - 1 ,len = 0;while(l < r){len = r - l;int temp = min(h[l],h[r]) * len;vol = vol < temp ? temp:vol;// 然后根据情况进行迁移// 关于这里如何移动,并不知道怎么调整if (h[l] < h[r])    l ++;else    r --; }return vol;
}

整数转罗马数字

  • 题目链接:整数转罗马数字
    在这里插入图片描述
个人实现
思路分析
  • 数字并不是很大,所以直接进行遍历,逐个位数进行修改
  • 直接暴力做
实现代码

在这里插入图片描述

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;const int N = 3999;
string intToRoman(int num) {// 不是4或者9开头,就减去最大值,并将该符号附加到结果,减去其值,将其与部分转换为罗马数字// 4或者9开头,使用减法形式// 只有10的次方可以连续出现三次,其他都不行// 将数字分成几个段落:// 1-3 ,可以使用最高位进行连续相加// 4:5-1// 6-8:5+1-3的组合// 9:10-1// 先处理1000,确定最高位int v = num / 1000,res = num % 1000;string s = "";if (v <= 3 && v >0)while(v)    s += "M" , v--;// 然后在获取百位v = res / 100,res %= 100;switch (v) {case 0:break;case 1:case 2:case 3:while(v){s += "C" , v--;}break;case 4:s += "CD";break;case 5:s += "D";break;case 6:s += "DC";break;case 7:s += "DCC";break;case 8:s += "DCCC";break;case 9:s += "CM";break;}// 然后在获取十位v = res / 10,res %= 10;switch (v) {case 0:break;case 1:case 2:case 3:while(v){s += "X" , v--;}break;case 4:s += "XL";break;case 5:s += "L";break;case 6:s += "LX";break;case 7:s += "LXX";break;case 8:s += "LXXX";break;case 9:s += "XC";break;}//然后在处理个位switch (res) {case 0:break;case 1:case 2:case 3:while(v){s += "I" , res--;}break;case 4:s += "IV";break;case 5:s += "V";break;case 6:s += "VI";break;case 7:s += "VII";break;case 8:s += "VIII";break;case 9:s += "IX";break;}return s;}
int main(){int n = 1;cout<<intToRoman(n)<<endl;
}
参考实现
思路分析
  • 这是一道模拟的题目,也就是找规律的题目。规则有限,直接打表也行
    *
  • 但是这里是定义结果临界值,如果大于特定的值,就减去对应的值,

在这里插入图片描述

实现代码
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;const int N = 3999;
string intToRoman(int n) {string s = "";int num[] = {1,4,5,9,10,40,50,90,100,400,500,900,1000};string numRep[] = {"I","IV","V","IX","X","XL","L","XL","C","CD","D","CM","M"};for (int i = 12; i >=  0; i --) {while(n >= num[i]){s += numRep[i];n -= num[i];}}cout<<s<<endl;
}
int main(){int n = 1;cout<<intToRoman(n)<<endl;
}

总结

  • 本来应该坚持一下,但是最近一直在忙论文,本来已经写好了,就差试验了,结果今天把实验做完了,发现实验效果差的不行,因该是方法不行,很难受,不过秋招在即,没什么时间了,就暂时放弃了。明天开始继续跟上了。毕竟论文已经投了,这是第二篇,就是没人给我看,我害怕自己毕不了业,中不了,所以才想写第二篇。不过现在看,每天抽点时间做实验吧,能成就成,不能成也没有办法。

这篇关于秋招突击——算法打卡——5/31——复习{采药问题、(状态压缩DP)小国王}——新做:{盛最多水的容器、整数转罗马数字}的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1026617

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

好题——hdu2522(小数问题:求1/n的第一个循环节)

好喜欢这题,第一次做小数问题,一开始真心没思路,然后参考了网上的一些资料。 知识点***********************************无限不循环小数即无理数,不能写作两整数之比*****************************(一开始没想到,小学没学好) 此题1/n肯定是一个有限循环小数,了解这些后就能做此题了。 按照除法的机制,用一个函数表示出来就可以了,代码如下

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

hdu1565(状态压缩)

本人第一道ac的状态压缩dp,这题的数据非常水,很容易过 题意:在n*n的矩阵中选数字使得不存在任意两个数字相邻,求最大值 解题思路: 一、因为在1<<20中有很多状态是无效的,所以第一步是选择有效状态,存到cnt[]数组中 二、dp[i][j]表示到第i行的状态cnt[j]所能得到的最大值,状态转移方程dp[i][j] = max(dp[i][j],dp[i-1][k]) ,其中k满足c

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig