Acm课程总结

Acm课程总结
ACM这个概念还是从上个学期知道的,当时有学长说到这个acm对于程序设计有很大的帮助,也就是跟着学长参加了acm早期的那个课程当时由于自己的懒惰心里当时不是那么跟得上以至于后来就逐渐的放弃了,现在想一下真的是有些后悔当时没有好好学。现如今,这次课程的结束也让我有了很多的感想;
知识点的总结:
第一次上课学习的就是STL:
stack栈,栈我记得从开始学了到现在几乎没怎么用过,栈就是一个单方向可通的容器,对他的操作也只有对应的函数,push()函数,top()函数pop()函数top函数size()函数
queue队列这个东西就是类似于排队一样所操作的函数跟其他的stl操作函数差不多先进先出关于bfs算法queue是经常使用的容器,back()返回最后一个元素
empty()如果队列空则返回真front()返回第一个元素pop()删除第一个元素push()在末尾加入一个元素size()返回队列中元素的个数
queue 的基本操作举例如下:
queue入队,如例:q.push(x); 将x 接到队列的末端。
queue出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问queue队首元素,如例:q.front(),即最早被压入队列的元素。
访问queue队尾元素,如例:q.back(),即最后被压入队列的元素。
判断queue队列空,如例:q.empty(),当队列空时,返回true。
访问队列中的元素个数,如例:q.size()
Lower -bound/upper-bound用法
num[] = {1,2,2,3,4,5};
lower_bound(num, num + 6, 2)为num + 1
upper_bound(num, num + 6, 2)为num + 3
lower找到第一个>=2的值的位置;
upper找到第一个>2的值的位置;这个操作一般用于查找一个区间的元素左开右闭;
set容器:特点是只能存不同的元素,会自动去除重复;
具体的操作:
insert()插入erase(val)删除值,erase(pos)指针并返回
map容器:特点就是映射类似于数组但是他的键值不再局限于仅仅是整数可以是字符串,结构体,但是如果是结构体的话得重载比较运算符因为map此时无法进行自动排序;
具体操作:
inset(make_pair(,))构成映射,count(val)查找键值为val的元素,erase(val)删除键值为val的,erase(pos)删除迭代器指针为pos的erase(pos,bos)删除指针pos到bos这个中间的元素,find(val)函数找键值为val的元素并且返回的是指针形式的multimap 就是map的键值可以是重复的;
优先队列:就是二叉树逐渐的通过比较最后把根结点得到想要的数值
贪心算法:这里分好几个经典的解题方法
背包问题:
背包问题
但是背包问题还分两种情况一种就是物品可分割一种就是物体不可分割,这两种情况都是考虑物品的性价比;
可分割情况:struct bag{
int w; //物品的重量
int v; //物品的价值
double c; //性价比
}a[1001]; //存放物品的数组
然后性价比降序排列(运用sort)
//形参n是物品的数量,c是背包的容量M,数组a是按物品的性价比降序排序
double knapsack(int n, bag a[], double c)
{
  double cleft = c;        //背包的剩余容量
  int i = 0;
  double b = 0;          //获得的价值
  //当背包还能完全装入物品i
  while(i<n && a[i].w<cleft)
  {
    cleft -= a[i].w;
    b += a[i].v;
    i++;
  }
  //装满背包的剩余空间
  if (i<n) b += 1.0a[i].vcleft/a[i].w;
  return b;
}这也是基本的结构。
这个是东西可以分开的,
删数问题:
string a;        //n位数a
int k;
cin>>a>>k;
//如果k≥n,数字被删完了
If (k >= a.size()) a.erase();
else while(k > 0)
{
  //寻找最近下降点
  int i;
  for (i=0; (i<a.size()-1) && (a[i] <= a[i+1]); ++i);
  a.erase(i, 1);    //删除xi
  k- -;
}
//删除前导数字0
while(a.size() > 1 && a[0] == ‘0’)
  a.erase(0, 1);
cout<<a<<endl;
还有一个是提水的问题:
#include <bits/stdc++.h>
using namespace std;
int n,m,w[10001],b[101],vm,s,maxb;
int main(int argc, char** argv) {
cin>>n>>m;//输入
for(int i=1;i<=n;i++)
cin>>w[i];//存每个人的接水量
for(int i=1;i<=m;i++)
{
b[i]=w[i];}
vm=n-m;//第一次接水在外面等的人数
while(vm>0){
s++;//时间
for(int i=1;i<=m;i++){
b[i]–;//循环一次
{
if(b[i]==0)//接完换人
if(vm>0){
b[i]=w[n-vm+1];
vm–;//外面等的人少一个
}
}else
continue;
}
}
for(int i=1;i<=m;i++)
if(b[i]>maxb) maxb=b[i];//记得当你循环完后水龙头里面还有人接,取max算上
cout<<s+maxb<<endl;;//输出
return 0;
}
活动安排:
#include
#include
#include <stdio.h>

using namespace std;

struct node
{
int s;
int f;
}w[20];

bool cmp(const node& a,const node& b)
{
return a.f<b.f; //按照结束时间降序排列。
}

int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>w[i].s>>w[i].f;
sort(w,w+n,cmp);
int j=0;
int cnt=1;
for(int i=1;i<n;i++)
{
if(w[i].s>=w[j].f)
{
cnt++;
j=i;
}
}
cout<<cnt<<endl;
return 0;
}
经典dp:
所谓dp就是动态的规划,不断地寻找更好的解,直到寻找到最优解为止,也就是所有的dp都有状态转移方程,经典dp就是一些简单的dp问题,0/1背包问题,最大字段和问题最大上升子序列,滑雪问题,
01背包:
for( int i = 1; i< nCost); i++)
{

for( int j = 1; j<=bagV; j++)

{
if(j<nVol[i])
nArr[i][j] = nArr[i-1][j];
else
nArr[i][j] = max(nArr[i-1][j] , nArr[i-1][j-nVol[i]] + nCost[i]);

这是没有优化的代码
优化空间:
for(i=1;i<ncost;i++)
for(j=bagV;j>=0;j–)
B(j)= max{B(j), B(j-w(i))+v(i)}

完全背包:
特点是每种物品可以无限制的使用可以选择放或者不放,肯定是多放价值高的重量小的;
int n, m;
cout << “请输入物品个数:”;
cin >> n;
cout << “请分别输入” << n << “个物品的重量和价值:” << endl;
for (int i = 1; i <= n; i++) {
cin >> weight[i] >> value[i];
}
cout << “请输入背包容量:”;
cin >> m;
for (int i = 1; i <= n; i++) {
for (int j = weight[i]; j <= m; j++) {
f[j] = max(f[j], f[j - weight[i]] + value[i]);
}
}
cout << “背包能放的最大价值为:” << f[m] << endl;
多重背包问题:
第i件物品总共有n[i]可用件数,不是无穷的但是也是不唯一的
int main() {
int n, m;
cout << “请输入物品个数:”;
cin >> n;
cout << “请分别输入” << n << “个物品的重量、价值和数量:” << endl;
for (int i = 1; i <= n; i++) {
cin >> weight[i] >> value[i] >> num[i];
}
int k = n + 1;
for (int i = 1; i <= n; i++) {
while (num[i] != 1) {
weight[k] = weight[i];
value[k] = value[i];
k++;
num[i]–;
}
}
cout << “请输入背包容量:”;
cin >> m;
for (int i = 1; i <= k; i++) {
for (int j = m; j >= 1; j–) {
if (weight[i] <= j) f[j] = max(f[j], f[j - weight[i]] + value[i]);
}
}
cout << “背包能放的最大价值为:” << f[m] << endl;
}

区间dp:就是把一个区间不断枚举出来在寻找最优解通过合并小区间上的最优解从而在整个大区间上获得最优解,具体阶梯模版
for(int len = 1;len<=n;len++){//枚举长度
for(int j = 1;j+len<=n+1;j++){//枚举起点,ends<=n
int ends = j+len - 1;
for(int i = j;i<ends;i++){//枚举分割点,更新小区间最优解
dp[j][ends]= min(dp[j][ends],dp[j][i]+dp[i+1][ends]+something);
}
}
}
状态压缩dp:
使用位操作的dp,
& 按位与 如果两个相应的二进制位都为1,则该位的结果值为1,否则为0
l 按位或 两个相应的二进制位中只要有一个为1,该位的结果值为1
^ 按位异或 若参加运算的两个二进制位值相同则为0,否则为1
~ 取反 ~是一元运算符,用来对一个二进制数按位取\反,即将0变1,将1变0
<< 左移 用来将一个数的各二进制位全部左移N位,右补0
*>> 右移 将一个数的各二进制位右移N位,移到右端 的低位被舍弃,对于无符号数,高位补0
搜索:
广度搜索:度搜索都是类似与二叉树一样的数据操作,
广度搜索可以由一个队列实现操作,先进先出到了头之后下一层再进入一次性查找;
深度搜索:套用递归的思想,顺着一条分支一直往下走直到找到满足条件的或者到头了为止再返回上一层依次类推;
二分法:
其实会了二分查找二分法也就差不多了,首先弄一个中间的标志,根据得出的数具与中间数据的相比较来决定缩小上限还是增大下限;
二叉树:
类似于树形状的存储数据的数据结构,并且每个结点都至多有两个结点,满二叉树就是每个父结点都有他的孩子,完全二叉树只能父结点的孩子是少右边的或者一个都没少或者都没有;
图论:
寻找最短几个点之间的最短路径,其实还是涉及到了dp的算法,主要有这么几个算法,弗洛伊德算法,迪杰斯特拉算法,ford算法,Kruskal算法,prim算法,
知识总结也就草草的总结这一些;
题目总结:
从一开始还是积极的做题但是到后来特别是学习dp的时候当时直接就是蒙了,根本不懂是什么原理也至于到现在做的题目很少,还是得通过暑假多做题来提升自己的能力啊,
做题的话,总是有些题当时得看很长时间才能读懂题目而且有时候还会读错题目就算是读懂了题目,自己还是没法找出来做题的方法,这个做题的方面上还是有许多的欠缺,知识是死的但是应用的人是活的,要想充分的应用知识就只能多做题,只有见识广了思路才有了,也就跟高中的数学一个样,并不是题目难而是自己见识短;
个人感想:
从一开始接触Acm我其实是抱着试试看的思想的,他们都说可以提高自己的算法能力,我一开始还是很积极的,假期里当时有些懒惰但是到后来觉得也得找些事情干我也就是每天都把老师给的题目做一下但是当时虽然说了vjudge这个东西我当时只是看了一眼觉得全是英文根本没法做,而且有些知识当时我是并不知道的,也就没在去做,到了一开学上课的时候他们都是一脸很明白的样子我却很是懵,但是逐渐的那些刚开始讲的东西也就明白了,因为都是些比较基础的东西,到了后来开始讲了算法,当时贪心算法我在寒假里还是有了解的而且还做了有关的一些水题,这一点理解起来也没什么难处,但是还是因为懒惰的原因导致了题目做的不是很多我记得贪心这一课题也就是做了一办多一点的题目,我不像他们有些人一样挑灯夜战在那做题,一方面我觉得这样效率非常的低,另一方面这样也会影响其他的人,还有就是心态的问题,其实有些的题目做不出来何必那么生气暴躁真是没有必要,慢下来仔细想想也许会想出来。dp这是一个噩梦的开始当时课上听的时候就是一脸懵而且课下做的题又是难到了离谱,这根本没法整,我也是从这里开始了慢慢的懈怠了,当时感觉是真的不爽为什么自己不能像他们一样随随便便的就把所有的题目都给ac了这一块停留的时间非常的长,后来学习的搜索我感觉比较好理解了,迫于每天学习的压力以及自己低效率的学习,还是没有跟得上做题,有一段时间当时是在讲数据结构当时没怎么有题目做当时是真的感觉自己很没用,脑子非常的笨,为什么像高中那样再难的题即使自己从来没见过也能比较轻松的解决那个问题,但是这一次在这块是真的不是那么的轻松,可能是我的逻辑思维能力是差的到家了,这一段没有题目的日子让我反思了好长时间,后来的一些算法其实从理解上来说还都可以没有什么难的地方主要是对于做题还是翻译的时候有时候难以理解那个题目大部分的话都是废话,还得自己不断的筛选,后来到了快结课了的时候不都是说要训练吗,我当时是想跟他们已经组队的三个队伍一样也能参加这样的比赛不说为了学校争光,也为了是提升子啊。刚开始USACO我成功的刷完了第一关后来又开始有了比赛现在也没怎么通关了,再加上c++程序设计一大些的事情,我也是很愁,到现在所有的课基本上都结课了时间是有了但是当时失去的现在却补不回来了,我也就只能暑假里再补习一下子,多做点题
关于做题时的心态:
关于这几次试水的比赛我其实很清楚自己的水平,也就是这些人中的低下游水平这都是自己当时没有努力的结果,做题的时候有些题是真的看不懂,好歹看懂了一个题却又忽略了很多东西却怎么也ac不了,这种心情差不多每一个在这种情况都会产生,又有谁不是一旦自己费劲心思的一道题终于ac了自己的内心是有多么的快乐当时的心情可以说是直接都上天了,非常的满足。但是又有多少人在这其中挣不下来的而转身选择了放弃,这一切都是需要自己坚持住才行。
关于以后:
我想在暑假里面多做些题,尽量早点来学校,这个暑假绝对是个刷题的战场我若是还是这么的垃圾,那我就果断地放弃了,这也说明了我不适合这个acm的学习,上天的恩赐是赐个有准备的人,但愿这句话是真理;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值