非常好的题!和spoj 的 Mobile Service有点相似,用记忆化搜索很容易解决

看了网上的题解,也是减掉一维,刚好可以开下数组 https://blog.lucien.ink/archives/224/

#include<bits/stdc++.h>
using namespace std;
#define maxn 2005
int n,A[maxn],B[maxn];
int dp[maxn][][][][]; //状态:准备去拉第i个人,当前在cur楼,另外三个人的目标楼层是abc
int dfs(int i,int cur,int a,int b,int c){
if(dp[i][cur][a][b][c]!=-)
return dp[i][cur][a][b][c];
int res=0x3f3f3f3f;
if(i>n){//终止状态,只要把abc送到终点即可
if(!a && !b && !c)res=;
if(a!=)res=min(res,dfs(i,a,,b,c)+abs(cur-a)+);//送到a
if(b!=)res=min(res,dfs(i,b,a,,c)+abs(cur-b)+);//送到b
if(c!=)res=min(res,dfs(i,c,a,b,)+abs(cur-c)+);//送到c
return dp[i][cur][a][b][c]=res;
}
//先放下abc的决策
if(a)res=min(res,dfs(i,a,,b,c)+abs(cur-a)+);
if(b)res=min(res,dfs(i,b,a,,c)+abs(cur-b)+);
if(c)res=min(res,dfs(i,c,a,b,)+abs(cur-c)+); //准备去拉一个人的决策:先去把i接上电梯
if(a&&b&&c){//电梯全满,再拉一个人需要先放下一个人
res=min(res,dfs(i+,B[i],a,b,c)+abs(cur-A[i])+abs(A[i]-B[i])+);
res=min(res,dfs(i+,a,B[i],b,c)+abs(cur-A[i])+abs(A[i]-a)+);
res=min(res,dfs(i+,b,a,B[i],c)+abs(cur-A[i])+abs(A[i]-b)+);
res=min(res,dfs(i+,c,a,b,B[i])+abs(cur-A[i])+abs(A[i]-c)+);
}
else {//先去接i,再拉一个人
if(!a)res=min(res,dfs(i+,A[i],B[i],b,c)+abs(cur-A[i])+);
else if(!b)res=min(res,dfs(i+,A[i],a,B[i],c)+abs(cur-A[i])+);
else if(!c)res=min(res,dfs(i+,A[i],a,b,B[i])+abs(cur-A[i])+);
}
return dp[i][cur][a][b][c]=res;
} int main(){
memset(dp,-,sizeof dp);
cin>>n;
for(int i=;i<=n;i++)cin>>A[i]>>B[i];
cout<<dfs(,,,,)<<'\n';
}

此外是滚动数组的版本(没有降维复杂度比较高)

#include<bits/stdc++.h>
using namespace std;
#define maxn 2005 int n,a[maxn],b[maxn],dp[][][][][][]; void calc(int &a,int b){
int tmp=min(a,b);
a=tmp;
} int main(){
cin>>n;
for(int i=;i<=n;i++)cin>>a[i]>>b[i];
memset(dp,0x3f,sizeof dp); int cur=;
dp[cur][][][][][]=*n;//开始停在1楼,因为n个人总共上下2*n次,所以直接加上这个值
for(int i=;i<=n;i++){//去接第i+1个人
for(int x=;x>=;x--)//这里必须逆序,因为把电梯里的人放下时的目标状态是dp[cur][][0][0][0][0],即消除掉后效性
for(int y=;y>=;y--)
for(int z=;z>=;z--)
for(int w=;w>=;w--)
for(int f=;f<=;f++){
int now=dp[cur][f][x][y][z][w];
if(now==0x3f3f3f3f)continue;
if(x== && i<n)//把第i+1个人放在位置x,更新状态到下一步
calc(dp[cur^][a[i+]][b[i+]][y][z][w],now+abs(f-a[i+]));
else if(x)//不接人把电梯里的人送到目的地
calc(dp[cur][x][][y][z][w],now+abs(f-x));
if(y== && i<n)
calc(dp[cur^][a[i+]][x][b[i+]][z][w],now+abs(f-a[i+]));
else if(y)
calc(dp[cur][y][x][][z][w],now+abs(f-y));
if(z== && i<n)
calc(dp[cur^][a[i+]][x][y][b[i+]][w],now+abs(f-a[i+]));
else if(z)
calc(dp[cur][z][x][y][][w],now+abs(f-z));
if(w== && i<n)
calc(dp[cur^][a[i+]][x][y][z][b[i+]],now+abs(f-a[i+]));
else if(w)
calc(dp[cur][w][x][y][z][],now+abs(f-w));
}
if(i<n){
memset(dp[cur],0x3f,sizeof dp[cur]);
cur^=;
}
}
int ans=0x3f3f3f3f;
for(int i=;i<=;i++)
ans=min(ans,dp[cur][i][][][][]);
cout<<ans<<'\n';
}

线性dp(记忆化搜索)——cf953C(经典好题dag和dp结合)的更多相关文章

  1. 【bzoj5123】[Lydsy12月赛]线段树的匹配 树形dp+记忆化搜索

    题目描述 求一棵 $[1,n]$ 的线段树的最大匹配数目与方案数. $n\le 10^{18}$ 题解 树形dp+记忆化搜索 设 $f[l][r]$ 表示根节点为 $[l,r]$ 的线段树,匹配选择根 ...

  2. 【BZOJ】1415 [Noi2005]聪聪和可可 期望DP+记忆化搜索

    [题意]给定无向图,聪聪和可可各自位于一点,可可每单位时间随机向周围走一步或停留,聪聪每单位时间追两步(先走),问追到可可的期望时间.n<=1000. [算法]期望DP+记忆化搜索 [题解]首先 ...

  3. [题解](树形dp/记忆化搜索)luogu_P1040_加分二叉树

    树形dp/记忆化搜索 首先可以看出树形dp,因为第一个问题并不需要知道子树的样子, 然而第二个输出前序遍历,必须知道每个子树的根节点,需要在树形dp过程中记录,递归输出 那么如何求最大加分树——根据中 ...

  4. poj1664 dp记忆化搜索

    http://poj.org/problem?id=1664 Description 把M个相同的苹果放在N个相同的盘子里,同意有的盘子空着不放,问共同拥有多少种不同的分法?(用K表示)5.1.1和1 ...

  5. 状压DP+记忆化搜索 UVA 1252 Twenty Questions

    题目传送门 /* 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 若 ...

  6. ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索

    ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...

  7. POJ 1088 DP=记忆化搜索

    话说DP=记忆化搜索这句话真不是虚的. 面对这道题目,题意很简单,但是DP的时候,方向分为四个,这个时候用递推就好难写了,你很难得到当前状态的前一个真实状态,这个时候记忆化搜索就派上用场啦! 通过对四 ...

  8. zoj 3644(dp + 记忆化搜索)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4834 思路:dp[i][j]表示当前节点在i,分数为j的路径条数,从 ...

  9. loj 1044(dp+记忆化搜索)

    题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26764 思路:dp[pos]表示0-pos这段字符串最少分割的回文 ...

随机推荐

  1. vuex之module的使用

    一.module的作用 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象.当应用变得非常复杂时,store 对象就有可能变得相当臃肿. 为了解决以上问题,Vuex 允许我们将 store 分 ...

  2. Web安全之环境搭建

    一. 工具集:Linux: Kali最新版(A/P:root/toor).Windows7/10. 靶机:OWASP_BWA(A/P:root/owaspbwa).DVWA.Mutillidae.We ...

  3. Tomcat免安装版踩坑

    下载解压 从官网下载Tomcat的压缩包解压到硬盘上(这里用的是toncat7),解压之后目录如下(Windows) bin 存放tomcat的一些命令脚本 conf 存放配置文件 lib 存放运行时 ...

  4. API equals方法 toString方法

    API  API: Application(应用) Programming(程序) Interface(接口)  不需要关心这些类是如何实现的,只需要学习这些类如何使用即可. equals方法 1.在 ...

  5. Vue学习笔记【16】——vue-resource 实现 get, post, jsonp请求

    除了 vue-resource 之外,还可以使用 axios 的第三方包实现实现数据的请求 之前的学习中,如何发起数据请求?原生.jQuery,需要操作DOM 常见的数据请求类型? get post ...

  6. CSS制作红桃心

    这里主要用到了before与after属性之前之后 代码: <!DOCTYPE html> <html> <head> <meta charset=" ...

  7. 概率——17icpc西安

    不知道为什么是这样子的.. #include<bits/stdc++.h> using namespace std; int m,n; int main(){ while(scanf(&q ...

  8. Alibaba Cloud Toolkit,你确定不来尝鲜一下?

    阿里云出了新的工具,Alibaba Cloud Toolkit,看看“toolkit”这个名字就知道它是一个工具集. 没错!它就是一个工具集,一个集打包部署发布以及探索分析程序的工具集.而我,目前还停 ...

  9. 剑指offer---2、二叉搜索树的后序遍历序列

    剑指offer---2.二叉搜索树的后序遍历序列 一.总结 一句话总结: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字 ...

  10. 拾遗:Git 常用操作回顾

    温故而知新,可以为师矣. Git 布局 工作区---->暂存区---->本地仓库---->远程仓库 Create Repository git init PATH git add P ...