1 条题解
-
0
自动搬运
来自洛谷,原作者为

Mr_QwQ
**搬运于
2025-08-24 21:59:47,当前版本为作者最后更新于2018-05-10 14:09:26,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文

AC的第一道IOI题目,发个题解纪念一下。
这个题是一个相当基础的dp,唯一的难点在于代码实现。
令dp[i][a1][a2][b1][b2]为当前送第i辆车,第一个矿前两次送a1和a2,第二个前两次送b1和b2。
然后直接看这辆车送第一个矿还是第二个就好了。
边界是第n+1辆车,某个矿前两辆车没送的情况就直接用0占位就好。
这里用的是记忆化,由于数据小,时空问题都不大。如果觉得记忆化可能会MLE/爆栈可以改用逆序dp(可以把i滚动掉),但是代码会复杂很多,不如记忆化好写,
像我这样的萌新可以先用记忆化写一遍,再照着写dp。代码:
#include <iostream> #include <cstdio> using namespace std; int n,type[100010],dp[100010][4][4][4][4]; char ch; char getchar(int){ char c='\0'; while(c!='M' && c!='F' && c!='B')c=getchar(); return c; } int food(char c){ if(c=='M')return 1; if(c=='F')return 2; if(c=='B')return 3; return -1; } int coal(int fa,int fb,int fc){ if(!fa && !fb)return 1; if(!fa)return (fb!=fc)+1; if(fa==fb && fb==fc)return 1; return (fa!=fb)+(fb!=fc)+(fa!=fc); } int dfs(int now,int a1,int a2,int b1,int b2){ if(now>n)return 0; if(dp[now][a1][a2][b1][b2])return dp[now][a1][a2][b1][b2]; return dp[now][a1][a2][b1][b2]=max(dfs(now+1,a2,type[now],b1,b2)+coal(a1,a2,type[now]),dfs(now+1,a1,a2,b2,type[now])+coal(b1,b2,type[now])); } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ ch=getchar(233); type[i]=food(ch); } printf("%d\n",dfs(1,0,0,0,0)); return 0; }
- 1
信息
- ID
- 3367
- 时间
- 1000ms
- 内存
- 18MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者