题目(vijos)
题目(BZOJ)
我写的是记忆化搜索......不知道为什么bzoj上面TLE了......
用dp[step][a1][b1][a2][b2]表示搜索到第step个餐车时,第一个矿洞前两餐分别为a1,b1,第二个矿洞前两餐为a2,b2,
然后记忆化搜索过去就行。把b1换到a1位置,在b1位置换上新的餐车,第二个矿洞也是这样。
(但为什么bzoj上TLE了?!)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> using namespace std; int n; char s[100005]; int p[100005]; int dp[100005][4][4][4][4]; inline int now(int x,int y,int z) { if (!x && !y && z) return 1; if (!x && y && z && y!=z) return 2; if (!x && y && z && y==z) return 1; if (x!=y && x!=z && y!=z) return 3; if (x==y && z!=x) return 2; if (y==z && x!=z) return 2; if (x==z && y!=x) return 2; if (x==y && y==z) return 1; } int dfs(int step,int a1,int b1,int a2,int b2) { if (step==n+1) return 0; if (dp[step][a1][b1][a2][b2]!=-1) return dp[step][a1][b1][a2][b2]; int tmp=max(dfs(step+1,b1,p[step],a2,b2)+now(a1,b1,p[step]),dfs(step+1,a1,b1,b2,p[step])+now(a2,b2,p[step])); return dp[step][a1][b1][a2][b2]=tmp; } int main() { scanf( scanf( memset(dp,-1,sizeof dp); for (register int i=1;i<=n;++i) { if (s[i]=='M') p[i]=1; else if (s[i]=='F') p[i]=2; else p[i]=3; } int ans=dfs(1,0,0,0,0); printf( return 0; }
然后在bzoj上无论怎样常数优化都不行......
然后无奈去看了看题解......
啥?滚动数组?话说这复杂度和我的不是差不多吗。
后来才发现......
滚动数组是用来优化memset的时间复杂度的......
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> using namespace std; int n; char s[100005]; int p[100005]; int dp[5][4][4][4][4]; int ans; inline int now(int x,int y,int z) { if (!x && !y && z) return 1; if (!x && y && z && y!=z) return 2; if (!x && y && z && y==z) return 1; if (x!=y && x!=z && y!=z) return 3; if (x==y && z!=x) return 2; if (y==z && x!=z) return 2; if (x==z && y!=x) return 2; if (x==y && y==z) return 1; } int main() { scanf( scanf( memset(dp,-1,sizeof dp); for (int i=0;i<n;++i) { if (s[i]=='M') p[i]=1; else if (s[i]=='F') p[i]=2; else p[i]=3; } dp[0][0][0][0][0]=0; for (int i=0;i<n;++i) for (int a1=0;a1<4;++a1) for (int b1=0;b1<4;++b1) for (int a2=0;a2<4;++a2) for (int b2=0;b2<4;++b2) { int x= if (dp[x][a1][b1][a2][b2]==-1) continue; dp[y][b1][p[i]][a2][b2]=max(dp[y][b1][p[i]][a2][b2],dp[x][a1][b1][a2][b2]+now(a1,b1,p[i])); dp[y][a1][b1][b2][p[i]]=max(dp[y][a1][b1][b2][p[i]],dp[x][a1][b1][a2][b2]+now(a2,b2,p[i])); } for (int a1=0;a1<4;++a1) for (int b1=0;b1<4;++b1) for (int a2=0;a2<4;++a2) for (int b2=0;b2<4;++b2) ans=max(ans,dp[ printf( return 0; }
Comments NOTHING