ProjectEuler215 Crack-free Walls


易知状态不会太多(\(3329\)个),直接搜一下,按照能不能连在后面建边,跑一遍dp即可

#include 

using namespace std;

struct S {
  int cnt;
  vector s;
}a[5000];

int n, m = 10, L = 32;
vector G[5000];
long long f[5000][15];
int tmp[100];

void dfs(int len, int cnt) {
  if(len >= L) {
    if(len > L) return ;
    a[++n].cnt = cnt;
    a[n].s.resize(cnt);
    for(int i = 0; i < cnt; ++i) a[n].s[i] = tmp[i+1];
    return ;
  }
  tmp[cnt+1] = 2;
  dfs(len+2, cnt+1);
  tmp[cnt+1] = 3;
  dfs(len+3, cnt+1);
}

bool check(S &x, S &y) {
  static int b[50];
  memset(b, 0, sizeof b);
  int sum = 0;
  for(int i = 0; i < x.cnt; ++i) b[sum+x.s[i]]++, sum += x.s[i];
  sum = 0;
  for(int i = 0; i < y.cnt; ++i) b[sum+y.s[i]]++, sum += y.s[i];
  for(int i = 2; i < L; ++i) if(b[i] > 1) return false;
  return true;
}

int main() {
  dfs(0, 0);
  for(int i = 1; i <= n; ++i) {
    f[i][1] = 1;
    for(int j = 1; j < i; ++j) if(check(a[i], a[j])) G[i].push_back(j), G[j].push_back(i);
  }
  for(int i = 2; i <= m; ++i)
    for(int u = 1; u <= n; ++u)
      for(int j = 0; j < G[u].size(); ++j)
        f[u][i] += f[G[u][j]][i-1];
  long long ans = 0;
  for(int i = 1; i <= n; ++i) ans += f[i][m];
  printf("%lld\n", ans);
  return 0;
}

相关