前面一篇博文写了玄学的做法,今天说说正解
首先看得出来原计算过程是一个递归的过程,相当于暴力求解,dfs超时就是因为包含了太多重复计算,而dp效率高在于去掉了重复计算,因此可以考虑将dfs改为记忆化搜索,直接在原给的代码中加入记忆化即可
#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
struct node{
node(){
mem(f, 0);
}
ll f[10];
void sum(){
f[7] = f[1] + f[2] + f[3] + f[4] + f[5] + f[6];
}
};
node operator + (const node& a, const node& b){
node c;
for (int i = 1; i <= 6; i++){
c.f[i] = a.f[i] + b.f[i];
}
return c;
}
bool vis[66][4][4][4];
node dp[66][4][4][4];
int getid(char a, char b){
if (a == 'A'){
if (b == 'B')return 1;
return 2;
}
else if (a == 'B'){
if (b == 'A')return 3;
return 4;
}
else if (a == 'C'){
if (b == 'A')return 5;
return 6;
}
}
node dfs(int n, char a, char b, char c){
if (vis[n][a - 'A'][b - 'A'][c - 'A']){
return dp[n][a - 'A'][b - 'A'][c - 'A'];
}
if (n == 1){
dp[n][a - 'A'][b - 'A'][c - 'A'].f[getid(a, c)]++;
vis[n][a - 'A'][b - 'A'][c - 'A'] = 1;
return dp[n][a - 'A'][b - 'A'][c - 'A'];
}
dp[n][a - 'A'][b - 'A'][c - 'A'] = dp[n][a - 'A'][b - 'A'][c - 'A'] + dfs(n - 1, a, c, b);
dp[n][a - 'A'][b - 'A'][c - 'A'].f[getid(a, c)]++;
dp[n][a - 'A'][b - 'A'][c - 'A'] = dp[n][a - 'A'][b - 'A'][c - 'A'] + dfs(n - 1, b, a, c);
vis[n][a - 'A'][b - 'A'][c - 'A'] = 1;
return dp[n][a - 'A'][b - 'A'][c - 'A'];
}
int main()
{
mem(vis, 0);
mem(dp, 0);
int n;
scanf("%d", &n);
node ans = dfs(n, 'A', 'B', 'C');
map<int, string> mp;
mp[1] = "A->B:";
mp[2] = "A->C:";
mp[3] = "B->A:";
mp[4] = "B->C:";
mp[5] = "C->A:";
mp[6] = "C->B:";
mp[7] = "SUM:";
ans.sum();
for (int i = 1; i <= 7; i++){
cout << mp[i];
printf("%lld\n", ans.f[i]);
}
return 0;
}