BZOJ_1609_[Usaco2008_Feb]_Eating_Together_麻烦的聚餐_(动态规划,LIS)
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1609
给出一串由1,2,3组成的数,求最少需要改动多少个数,使其成为不降或不升序列.
分析
法1:改动一些数字后变为不升(不降)序列,那么除了需要改动的数字以外,其他的数字本身满足不升(不降),所以求最长不升(不降)子序列即可.O(nlogn)
法2:考虑搜索的思路,枚举当前位置的值,如果和原来的值相等,那么不许改动,否则改动数+1,然后搜索下一个位置,值要大于等于当前位置的改动数.这样会有重叠子问题,所以可以记忆化,倒过来就是dp.
dp[i][j]表示前i个,结尾为j的改动数,则有:
如果a[i]==j,则dp[i][j]=dp[i-1][k](k<=j)
如果a[i]!=j,则dp[i][j]=dp[i-1][k]+1(k<=j) O(n).
LIS:
O(n^2)的算法:
#include <bits/stdc++.h>
using namespace std; const int maxn=+;
int n,ans;
int a[maxn],dp[maxn]; int main(){
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=n;i++){
dp[i]=;
for(int j=;j<i;j++)
if(a[j]<=a[i]) dp[i]=max(dp[j]+,dp[i]);
ans=max(ans,dp[i]);
}
for(int i=;i<=n;i++){
dp[i]=;
for(int j=;j<i;j++)
if(a[j]>=a[i]) dp[i]=max(dp[j]+,dp[i]);
ans=max(ans,dp[i]);
}
printf("%d\n",n-ans);
return ;
}
O(nlogn)的算法:
#include <bits/stdc++.h>
using namespace std; const int maxn=+,INF=0x7fffffff;
int n,ans;
int a[maxn],b[maxn],dp[maxn]; int main(){
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]), b[n+-i]=a[i];
fill(dp+,dp+n+,INF);
for(int i=;i<=n;i++)
*upper_bound(dp+,dp+n+,a[i])=a[i];
ans=lower_bound(dp+,dp+n+,INF)-(dp+);
fill(dp+,dp+n+,INF);
for(int i=;i<=n;i++)
*upper_bound(dp+,dp+n+,b[i])=b[i];
ans=max(ans,lower_bound(dp+,dp+n+,INF)-(dp+));
printf("%d\n",n-ans);
return ;
}
快得不是一点点...
O(n)的算法:
#include <bits/stdc++.h>
using namespace std; const int maxn=+,INF=0x3fffffff;
int n,ans;
int a[maxn];
int dp[maxn][];
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
ans=INF;
for(int i=;i<=n;i++)for(int j=;j<=;j++) dp[i][j]=INF;
for(int i=;i<=n;i++)for(int j=;j<=;j++)for(int k=;k<=j;k++)
if(a[i]==j) dp[i][j]=min(dp[i][j],dp[i-][k]);
else dp[i][j]=min(dp[i][j],dp[i-][k]+);
for(int i=;i<=;i++) ans=min(ans,dp[n][i]);
for(int i=;i<=n;i++)for(int j=;j<=;j++) dp[i][j]=INF;
for(int i=n;i>=;i--)for(int j=;j<=;j++)for(int k=;k<=j;k++)
if(a[i]==j) dp[i][j]=min(dp[i][j],dp[i+][k]);
else dp[i][j]=min(dp[i][j],dp[i+][k]+);
for(int i=;i<=;i++) ans=min(ans,dp[][i]);
printf("%d\n",ans);
}
这里用到了STL里的二分查找.对于严格上升子序列,找到dp数组中a[i]的下界(满足dp[k]>=a[i]的最小的k(上界也可以,因为没有重复所以不会取等))即可,这样的话如果和以前的相同就覆盖了.对于这个问题,求的是不降子序列,所以相同的不能覆盖,所以我们找到dp数组中a[i]的上界(满足dp[k]>a[i]的最小的k),这样如果和以前相同的话就继续往后排,把原来上升序列中更大的结尾更新小.
对于求严格下降子序列,就需要找满足dp[k]<=a[i]的最小的k,不严格的就是dp[k]<a[i]的最小的k.
1609: [Usaco2008 Feb]Eating Together麻烦的聚餐
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 1326 Solved: 801
[Submit][Status][Discuss]
Description
为
了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐。每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想所有第3批就餐的奶牛排在队尾,队伍的前端由设定
为第1批就餐的奶牛占据,中间的位置就归第2批就餐的奶牛了。由于奶牛们不理解FJ的安排,晚饭前的排队成了一个大麻烦。
第i头奶牛有一张标明她用餐批次D_i(1 <= D_i <= 3)的卡片。虽然所有N(1 <= N <=
30,000)头奶牛排成了很整齐的队伍但谁都看得出来,卡片上的号码是完全杂乱无章的。
在若干次混乱的重新排队后,FJ找到了一种简单些的方法:奶牛们不动,他沿着队伍从头到尾走一遍把那些他认为排错队的奶牛卡片上的编号改掉,最终得到一个
他想要的每个组中的奶牛都站在一起的队列,例如111222333或者333222111。哦,你也发现了,FJ不反对一条前后颠倒的队列,那样他可以让
所有奶牛向后转,然后按正常顺序进入餐厅。
你也晓得,FJ是个很懒的人。他想知道,如果他想达到目的,那么他最少得改多少头奶牛卡片上的编号。所有奶牛在FJ改卡片编号的时候,都不会挪位置。
Input
第1行: 1个整数:N 第2..N+1行: 第i+1行是1个整数,为第i头奶牛的用餐批次D_i
Output
第1行: 输出1个整数,为FJ最少要改几头奶牛卡片上的编号,才能让编号变成他设想中的样子
Sample Input
1
3
2
1
1
输入说明:
队列中共有5头奶牛,第1头以及最后2头奶牛被设定为第一批用餐,第2头奶牛的预设是第三批用餐,第3头则为第二批用餐。
Sample Output
输出说明:
如果FJ想把当前队列改成一个不下降序列,他至少要改2头奶牛的编号,一种可行的方案是:把队伍中2头编号不是1的奶牛的编号都改成1。不过,如果FJ选择把第1头奶牛的编号改成3就能把奶牛们的队伍改造成一个合法的不上升序列了。
HINT
Source
BZOJ_1609_[Usaco2008_Feb]_Eating_Together_麻烦的聚餐_(动态规划,LIS)的更多相关文章
- Bzoj 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 二分
1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1272 Solve ...
- BZOJ1609: [Usaco2008 Feb]Eating Together麻烦的聚餐
1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 938 Solved ...
- BZOJ 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐( LIS )
求LIS , 然后用 n 减去即为answer ---------------------------------------------------------------------------- ...
- BZOJ 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐
1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Description 为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐.每天晚饭前,奶牛们都会在餐厅前排队入内,按F ...
- 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐
1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1010 Solv ...
- BZOJ_1672_[Usaco2005 Dec]Cleaning Shifts 清理牛棚_动态规划+线段树
BZOJ_1672_[Usaco2005 Dec]Cleaning Shifts 清理牛棚_动态规划+线段树 题意: 约翰的奶牛们从小娇生惯养,她们无法容忍牛棚里的任何脏东西.约翰发现,如果要使这群 ...
- 51nod_1412_AVL树的种类_动态规划
51nod_1412_AVL树的种类_动态规划 题意: 平衡二叉树(AVL树),是指左右子树高度差至多为1的二叉树,并且该树的左右两个子树也均为AVL树. 现在问题来了,给定AVL树的节点个数n,求有 ...
- BZOJ【1609】 麻烦的聚餐
609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1198 Solved ...
- 非 动态规划---LIS
题目:一个序列有N个数:A[1],A[2],…,A[N],求出最长非降子序列的长度.(见动态规划---LIS) /* 题目:一个序列有N个数:A[1],A[2],…,A[N],求出最长非降子序列的长度 ...
随机推荐
- 详解Windows 7系统中IE8/IE9/IE10三个版本的关系(转)
今年(2013)年初,微软开放了姗姗来迟的 IE10 for Windows 7 版本下载.至此,Windows 7 平台上可以运行三个 IE 浏览器版本.虽然 Windows 与 IE 经历了诸多版 ...
- 我的VIM.rc
我的VIM.rc """""""""""""""& ...
- 常用Linux/Unix/Mac Os命令
常用Linux/Unix/Mac OS命令 参考: 1.50 Most Frequently Used UNIX / Linux Commands (With Examples)
- N的N次方(高校俱乐部)
最近一直在刷字符串和线段树,也越来越少玩高校俱乐部,无聊看到一题N的N次方的问题,脑海中各种打表就涌现出来了. 弄了不一会儿,就写完了,马上提交,但是系统好像出了问题,提示"哦哦,出了点状况 ...
- 基于libuv库的UDP收/发广播消息代码实现
uv_send(发送端): #include "uv.h" #include "task.h" #include <stdio.h> #includ ...
- 云盾正常扫描云服务器的IP是什么
问题:云盾正常扫描云服务器的IP是什么? 解答:云盾扫描云服务器的的IP段固定为 42.120.145.0/24 110.75.105.0/24 110.75.185.0/24 110.75 ...
- jQuery 中的防冲突(noConflict)机制
许多的 JS 框架类库都选择使用 $ 符号作为函数或变量名,jQuery 是其中最为典型的一个.在 jQuery 中,$ 符号只是 window.jQuery 对象的一个引用,因此即使 $ 被删除,w ...
- div+css实现未知宽高元素垂直水平居中
div+css实现未知宽高元素垂直水平居中.很多同学在面试的时候都会遇到这样的问题:怎么用div+css的方法实现一个未知宽高的弹出框(或者图片)垂直水平居中??如果用JS的话就好办了,但是JS的使用 ...
- CSS3 animation-fill-mode 属性
现在专注于移动端开发项目,对于动画这个点是非常重要的,每当我遇到一个新的知识点,我就会和大家一起分享 animation-fill-mode :把物体动画地从一个地方移动到另一个地方,并让它停留在那里 ...
- MySQL大数据量快速分页实现
一般刚开始学SQL语句的时候,会这样写 代码如下: SELECT * FROM table ORDER BY id LIMIT 1000, 10; 但在数据达到百万级的时候,这样写会慢死 代码如下: ...