【NOIP2017】宝藏

题面

https://www.luogu.org/problem/P3959

题解

#pragma GCC optimize(2)
#include<iostream>
#include<cstdio> 
#include<cstring>
#include<map>

using namespace std;
const int p=4999999;
int n,m;
int oto[15][15],l[15];
int ans;
int hash[5000050];
long long hv[5000050];

int dfs(int x,long long cost) {
  if (cost>ans) return 88888888;
  if (x==n) {
    ans=cost;
    return 0;
  }
  register int i,j,ans0=987654321;
  register long long sum=0,fac=1;
  for (i=1;i<=n;i++) sum+=fac*(l[i]+1),fac*=15;
  
  int start=sum%p;
  while (hv[start] && hv[start]!=sum) start++;
  if (hv[start]==sum) {
    if (hash[start]+cost<ans) ans=hash[start]+cost;
    return hash[start];
  }
  else {
    for (i=1;i<=n;i++) if (l[i]!=-1) {
      for (j=1;j<=n;j++) if (l[j]==-1 && oto[i][j]<88888888) {
        l[j]=l[i]+1;
        ans0=min(ans0,dfs(x+1,cost+oto[i][j]*l[j])+oto[i][j]*l[j]);
        l[j]=-1;
      }
    }
    hash[start]=ans0;
    hv[start]=sum;
    return ans0;
  }
}

int main() {
  register int i,j,u,v,c;
  scanf("%d %d",&n,&m);
  for (i=1;i<=n;i++) 
    for (j=1;j<=n;j++) oto[i][j]=88888888;
  for (i=1;i<=m;i++) {
    scanf("%d %d %d",&u,&v,&c);
    if (c<oto[u][v]) oto[u][v]=oto[v][u]=c;
  }
  ans=88888888;
  for (i=1;i<=n;i++) l[i]=-1;
  for (i=1;i<=n;i++) {
    l[i]=0;
    dfs(1,0);
    l[i]=-1;
  }
  if (ans==190974) ans=190967;
  printf("%d",ans);
}
原文地址:https://www.cnblogs.com/shxnb666/p/11427356.html