非常好的题!和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. 理解First-Class Functions

    def logger(msg): def log_message(): print('Log:', msg) return log_message # 返回的是函数 log_hi = logger(' ...

  2. vue-cli下的vuex的极简Demo(实现加1减1操作)

    1.vue-cli搭建好项目之后,使用npm安装vuex npm install vuex --save 2.在项目目录中构建vuex目录(这里我新建了store的文件夹,里面新建了store.js文 ...

  3. leetcode-160周赛-5239-循环码排列

    题目描述: 参考格雷编码: class Solution: def circularPermutation(self, n: int, start: int) -> List[int]: res ...

  4. mycat简介

    开源数据库中间件-MyCat简介 如今随着互联网的发展,数据的量级也是撑指数的增长,从GB到TB到PB.对数据的各种操作也是愈加的困难,传统的关系性数据库已经无法满足快速查询与插入数据的需求.这个时候 ...

  5. xlwings结合dataframe数据的写入

    一.代码 import xlwings as xw import pandas as pd xl_path=r'***' df_path=r'***' df=pd.read_excel(df_path ...

  6. 带头结点的循环单链表----------C语言

    /***************************************************** Author:Simon_Kly Version:0.1 Date: 20170520 D ...

  7. PAT_A1067#Sort with Swap(0, i)

    Source: PAT A1067 Sort with Swap(0, i) (25 分) Description: Given any permutation of the numbers {0, ...

  8. pcre2 正则库

    \S+ 不能匹配到字符串末尾的最后一个字段

  9. Servlet.init() for servlet [springmvc] threw exception

    项目还没开始做,就碰到那么多问题.. 报错一:/oa/news/%E6%A0%8F%E7%9B%AE%E7%AE%A1%E7%90%86.jsp 1.一开始是jsp的页面名称为中文,改了 2.接着仍然 ...

  10. JHipster研究

    liquibase工作原理: master.xml用来维护所有变更记录文件引用 changelog文件夹用来保存具体的变更细节 系统启动时会比较master.xml中include的file,应用差异 ...