2018-4-15

1.石子合并问题
1)设有N堆沙子排成一排,其编号为1,2,3,…,N(N<=100)。每堆沙子有一定的数量。现要将N堆沙子并成为一堆。归并的过程每次将任意两堆沙子堆成一堆(每次合并花费的代价为当前两堆沙子的总数量),这样经过N-1次归并后成为一堆,归并的总代价为每次合并花费的代价和。找出一种合理的归并方法,使总的代价最小。

我们可以使用贪心算法,每次只合并两个数量最小的沙子,所得到的结果就是最优解了。

其实这就是哈夫曼编码的变形。

每一次都要进行排序,虽然有点智障,但是还是写了…(注释的地方),
我的想法是每次将合并过后的值插入到它合适的位置,使得剩下的还是有序的即可。

#include<iostream>
#include<algorithm>
using namespace std;const int N = 100;
int x[N+1];
int n;int main(){int i,j;while (cin>>n){int sum=0;for (i=0;i<n;i++){cin>>x[i];}sort(x,x+n);// for (i=1;i<n;i++){//     sum+=x[i]+x[i-1];//     x[i]=x[i]+x[i-1];//     sort(x+i,x+n);// }for (i=1;i<n;i++){int tmp=x[i]+x[i-1];sum+=tmp;j=i+1;while (tmp>x[j]&&j<n){x[j-1]=x[j];j++;}x[j-1]=tmp;}cout<<sum<<endl;}return 0;
}

2)倘若我们每次只能合并相邻的两个石子呢?
贪心这个时候就不可以了,因为我们无法保证全局最优,虽然不对,但是我还是写了…

#include<iostream>
#include<vector>
#define inf 0x3f3f3f3f
using namespace std;int n;int main(){vector<int>vec;while (cin>>n){int a;for (int i=0;i<n;i++){cin>>a;vec.push_back(a);}int cnt=0;for (int i=0;i<n-1;i++){int tmp=inf,k=0;for (int j=1;j<vec.size();j++){if (vec[j]+vec[j-1]<tmp){tmp=vec[j]+vec[j-1];k=j;}}cnt+=tmp;vec.erase(vec.begin()+k);vec.erase(vec.begin()+k-1);vec.insert(vec.begin()+k-1,tmp);}   cout<<cnt<<endl;}return 0;
}

其实正确的解法应该是用动态规划求解:

#include<iostream>
using namespace std;const int N = 1000;
int x[N+1],dp[N+1][N+1],s[N+1];
int n;int main(){while (cin>>n){for (int i=1;i<=n;i++){cin>>x[i];s[i]=s[i-1]+x[i];}for (int l=2;l<=n;l++){for (int i=1;i<=n-l+1;i++){int j=i+l-1;dp[i][j]=N;for (int k=i;k<j;k++){dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j])+s[j]-s[i]+x[i];}}}
//      for (int i=1;i<=n;i++){//          for (int j=1;j<=n;j++){//              cout<<dp[i][j]<<" ";
//          }
//          cout<<endl;
//      }cout<<dp[1][n]<<endl;}return 0;
}

3)其实最终的题目应该是我们的这个沙子堆是环形的!

其实对于环形问题我们之前有过涉及,就是在直线后面再补充那么多就可以了!就是与USACO里面的那个项链问题差不多!

#include<iostream>
using namespace std;const int N = 2000;
int x[N+1],dp[N+1][N+1],s[N+1];
int n;int main(){while (cin>>n){for (int i=1;i<=n;i++){cin>>x[i];s[i]=s[i-1]+x[i];}for (int i=1;i<=n;i++){x[i+n]=x[i];s[i+n]=s[i+n-1]+x[i];}for (int l=2;l<=n;l++){ //最多还是合并 n 堆沙石子 for (int i=1;i<=2*n-l+1;i++){int j=i+l-1;dp[i][j]=N;for (int k=i;k<j;k++){dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);}dp[i][j]+=s[j]-s[i]+x[i];}}int res=N;for (int i=1;i<=n;i++){res=min(res,dp[i][i+n-1]);} cout<<res<<endl;}return 0;
}

2.整数划分问题
自行车选手在训练时,需要围绕着场地骑行N圈。给了使得训练有效,可以一次把N全部骑完,
也可以分成若干次完成,但每次都比上一次骑的圈数要多,那么完成一次训练即骑完N圈,
有多种训练方式

样例输入
6

样例输出
4

//例如,当 N = 6 时,有以下四种训练方案:
6
1 2 3
1 5
2 4

这个题目其实就是一个整数划分问题,整数划分又分为好多种:
1)将n划分成若干正整数之和的划分数
其实这是一个方苹果的问题,假设f(n,m)表示将n个苹果放在m个篮子里面,那么我们一共有两种情况:如果n>m的话,我们一定会有空的篮子,也就是等同于f(m,m),反之n

#include<iostream>
using namespace std;int n,cnt;void dfs(int sum,int pre){if (sum>n) return ;if (sum==n){cnt++;return ;}for (int i=pre;i<=n;i++){dfs(sum+i,i+1);}
}int main(){while (cin>>n){cnt=0;dfs(0,1);cout<<cnt<<endl;}return 0;
}

实际上应该是用动态规划问题…

3.最长不下降子序列问题
若干人排成一行,且身高分别为b1,b2,…,bn。准备从中选出一组满足身高不降的人组成一队。

例如13,7,9,16,38,24,37,18,44,19,21,22,63,15。
有13<16<38<44<63 长度为5的不下降子序列。
但经过观察,实际还有7<9<16<18<19<21<22<63 长度为8的不下降子序列。
给出最长队列的长度。

【输入格式】

第一行为n,表示n(n≤100000)个数。第二行为n个数的值。

【输出格式】

一个整数。

【输入样例】

4

1 3 1 2

【输出样例】

2

简单的动态规划问题:

#include<iostream>
using namespace std;const int N = 100000;
int x[N+1],dp[N+1];
int n;int main(){while (cin>>n){for (int i=1;i<=n;i++){cin>>x[i];}for (int i=1;i<=n;i++){dp[i]=1;for (int j=1;j<i;j++){if (x[j]<=x[i]){dp[i]=max(dp[j]+1,dp[i]);}}}int res=0;for (int i=1;i<=n;i++){res=max(res,dp[i]);}cout<<res<<endl;}return 0;
}

4.最长不下降子序列的升级问题
为了外来导弹袭击,最新的导弹拦截系统已经研制好了.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。
某天,雷达捕捉到了导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000 的正整数),计算这套系统最多能拦截多少导弹和如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

【输入样例】

389 207 155 300 299 170 158 65

【输出样例】

6(最多能拦截的导弹数)

2(要拦截所有导弹最少要配备的系统数)

#include<iostream>
using namespace std;const int N = 100000;
int x[N+1],dp[N+1];
int n;int main(){int i=0;while (cin>>x[i]){i++;if (getchar()=='\n') break;}n=i;for (int i=1;i<=n;i++){dp[i]=1;for (int j=1;j<i;j++){if (x[j]>=x[i]){dp[i]=max(dp[j]+1,dp[i]);}}}int res=0;for (int i=1;i<=n;i++){res=max(res,dp[i]);}cout<<res<<endl;for (int i=1;i<=n;i++){dp[i]=1;for (int j=1;j<i;j++){if (x[j]<=x[i]){dp[i]=max(dp[j]+1,dp[i]);}}}res=0;for (int i=1;i<=n;i++){res=max(res,dp[i]);}cout<<res<<endl;return 0;
}

这里需要我们用一个结论:求…等于最长非递增子序列。

ACM第一次集训 - 动态规划问题相关推荐

  1. acm暑期集训_2020.07.02

    acm暑期集训_2020.07.02 任务清单 1. 回顾ZUCC蓝桥杯热身赛-1中A.B.C题中涉及的知识点 2. 补题-----ZUCC蓝桥杯热身赛-1中D题 A题------洛谷-P1548 棋 ...

  2. ACM暑假集训总结(2014年夏)

    ACM暑假集训总结 这篇总结本来是打算暑假集训结束后, UVa上刷够300题, 给这一路留个纪念, 可最后竟然给了自己个大耳光--298. Hehe. 既然打算写了,那该干的就得干. 一个耳光没打够, ...

  3. ACM暑假集训训练总结报告

    为期一个月的ACM暑假集训过去了,想一想,真是光阴似箭,但与以往的不同,没有哀伤,而是满满的充实,这一个月说,不得不累,虽然心里压力没有高三的强,但是时间上基本差不多,每天真的即是三点一线,日复一日. ...

  4. 中南大学2019年ACM寒假集训前期训练题集(基础题)

    先写一部分,持续到更新完. A: 寒衣调 Description 男从戎,女守家.一夜,狼烟四起,男战死沙场.从此一道黄泉,两地离别.最后,女终于在等待中老去逝去.逝去的最后是换尽一生等到的相逢和团圆 ...

  5. ACMer菜鸟的ACM寒假集训感悟

    呵呵,在不知不觉中一个假期就这么过去了啊-总的来说感觉这个假期还是比较充实的,集训虽然很累,但是感觉很好.每一件事过去都要有一个总结,下面写写我对集训的总结吧. 坦白的说一开始真的很期待集训的开始,因 ...

  6. ACM杂题——动态规划_背包问题

    ACM杂题K - I NEED A OFFER!--动态规划_背包问题优化解法 题目描述 Speakless很早就想出国,现在他已经考完了所有需要的考试,准备了所有要准备的材料,于是,便需要去申请学校 ...

  7. 变种 背包问题_【朝夕的ACM笔记】动态规划-背包问题

    [朝夕的ACM笔记]目录与索引 背包问题 一.0/1背包 1.1 问题描述 有 件物品和一个大小为 的背包,以及若干物品,每种物品只有一件,大小分别为 ,其价值分别为 .问题:将哪些物品装入背包,可使 ...

  8. 【初学线段树,看这篇文章准没错】线段树(单点修改and区间修改)acm寒假集训日记22/1/10

    线段树 线段树是算法竞赛中常用的用来维护区间信息的数据结构.是一名ACMer 需要掌握的一种基础.重要的数据结构线段树可以在O(logN)的时间复杂度内实现单点修改,区间修改,区间查询(区间求和,区间 ...

  9. 最少换乘(最短路+恶心的输入)acm寒假集训日记22/1/3 or 22/1/4

    题目如下: AC代码如下: #include<iostream> #include<cstring> #include<cstdio> using namespac ...

最新文章

  1. vs2010下使用ADO.NET Entity Data Model
  2. Python3 安装PyMySQL
  3. 桌面支持--电脑出现临时账户--解决办法
  4. WinForm 2.0 textBox作为参数的查询,显示在DataGridView
  5. jQueryh插件imgareaselect
  6. Maven(5)--常用插件
  7. 程序员面试金典 - 面试题 17.26. 稀疏相似度(哈希map)
  8. java.util.timertask_java.util.TimerTask翻译
  9. HTML textarea 标签
  10. 【云栖大会】站在时间轴上看基础设施
  11. matlab 变量和数组中,求助:如何将带有符号变量的运算结果储存到数组中
  12. 弹出窗弹出两次的原因
  13. SQL函数字符串分拆
  14. atitit 2017年学业计划 v5 r818.xlsx
  15. ajax里的data的用法,Jquery中ajax方法data参数的用法
  16. 迅雷离线下载脚本 — LinuxTOY
  17. 上海证券综合指数昨天成功击破1000点
  18. 尤雨溪 6 月 4 日的 Vue 技术分享
  19. 微信小程序文本框保留两位小数(非四舍五入)
  20. 笔记:centos7 换内核安装锐速(该方法不好用,不建议)

热门文章

  1. java 变量序列化_Java序列化与静态变量
  2. ubuntu下ZED相机开发环境安装
  3. Manuscript match— 找到最适合你文章的那个ta(之期刊杂志)
  4. Ps胶片颗粒效果插件:Imagenomic Realgrain for Mac
  5. 一分钟学会在Mac中如何将文件批量重命名
  6. anaconda和python的区别_anaconda和python区别
  7. OJ(Online Judge)系统汇总
  8. 1.5 编程基础之循环控制 35 求出e的值
  9. 同一个页面提交多个form表单方法(详细)
  10. hibernate实战第二版 蒲成带目录_太NB了! 阿里程序员带你玩转Spring:脑图+实战五+面试百问+知识总结...