Evanyou Blog 彩带

  啦啦啦啦——又是五月天的歌,题目传送门

  这道题比之前两道真的不是同一级别的,这里我这个蒟蒻也讲不清,不如看下这位大佬的吧,他的写的已经非常清楚了:Z-Y-Y-S,这里我就只放下我的代码,也是按照这位大佬的思路做的:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 50005
using namespace std;
typedef long long ll;
ll f[1<<18+1],dis[N],len[105],cost[105][105];
int a[N],b[N],s[N],n,m,k,cnt;queue<int>team;
inline int read()
{
  char ch=getchar();int num=0;bool flag=false;
  while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
  while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
  return flag?-num:num;
}
void BFS()
{
  for(int i=1;i<=cnt;i++){
    memset(dis,-1,sizeof(dis));
    while(!team.empty())team.pop();
    team.push(s[i]);dis[s[i]]=0;
    while(!team.empty()){
      int u=team.front();
      team.pop();
      for(int j=1;j<=m;j++){
    for(int l=-1;l<=1;l+=2){
      int v=u+l*len[j];
      if(v>=1&&v<=n&&dis[v]==-1){
        dis[v]=dis[u]+1;
        if(b[v])cost[i][b[v]]=dis[v];
        team.push(v);
      }
    }
      }
    }
  }
}
void ready()
{
  n=read();k=read();m=read();
  for(int i=1;i<=k;i++)a[read()]=1;
  n++;
  for(int i=1;i<=n;i++)b[i]=a[i]^a[i-1];
  for(int i=1;i<=n;i++)
    if(b[i]){b[i]=++cnt;s[cnt]=i;}
  for(int i=1;i<=m;i++)len[i]=read();
  BFS();
}
void work()
{
  memset(f,127/3,sizeof(f));
  f[0]=0;
  for(int i=0;i<=(1<<cnt)-1;i++){
    for(int j=2;j<=cnt;j++)
      if((i&(1<<j-1))==0){
    for(int k=1;k<=j-1;k++)
      if((i&(1<<k-1))==0){
        if(cost[j][k]){
          int v=i|(1<<j-1);
          v|=(1<<k-1);
          f[v]=min(f[v],f[i]+cost[j][k]);
        }
      }
      }
  }
  printf("%lld",f[(1<<cnt)-1]);
}
int main()
{
  ready();
  work();
  return 0;
}
原文地址:https://www.cnblogs.com/cytus/p/7782194.html