题目描述
贝西喜欢去洞穴探险。这次她去的地方由 N 个洞穴组成,编号分别是 1 到 N,1 号洞穴是出发
的起点。
洞穴之间由 M 条隧道相连,双向通行,第 i 条隧道连接 A i 和 B i 。每条隧道有个尺寸,第 i 条
隧道的尺寸为 W i ,如果贝西的身材超过了隧道的尺寸,就钻不过去了。贝西的身材可用一个数字来
描述,一开始是 0。
前期准备时,贝西已在 K 个里洞穴存放了食物,她当然不会放过它们。当她吃掉一份食物后,
身材就会增加 1。在探险的过程中,她想吃掉尽量多的食物,但要保证最后能返回起点。请帮她计划
一下,什么样的路线才能吃到最多的食物?
注意,探险的路线可以重复,所以路过有食物时,可以留到下次路过的时候再吃。
输入
• 第一行:三个整数 N,M 和 K,1 ≤ N ≤ 100,1 ≤ M ≤ 1000,1 ≤ K ≤ 14
• 第二行到第 K+1 行:第 i+1 行有一个整数 C i ,表示在第 C i 号洞穴里有一份食物,1 ≤ C i ≤ N
• 第 K +2 行到第 K +M +1 行:第 i+K +1 行有三个整数 A i ,B i 和 W i ,1 ≤ A i ,B i ≤ N,1 ≤
W i ≤ 100
输出
• 单个整数:表示贝西最多能吃几份食物
样例输入
6 7 5 1 2 3 4 5 1 2 3 3 6 2 6 2 10 2 4 1 5 1 1 4 5 1 1 6 1
样例输出
4
提示
先吃 5 号洞里的,再吃 3,2,最后走回 1,
吃掉 1 里的最后一份食物
题解:
K<=14 很明显可以状压 ,然后发现想不出什么方程式,于是就上状压搜索,分析复杂度(1<<K)*N = 10^6 随便水过.
于是上记忆搜乱搞 F[i][j] 到i这个点状态为j 是否走过
注意:如果有食物在1号点,注意特判
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 const int N=105,M=1005,Z=14; 8 int gi(){ 9 int str=0;char ch=getchar(); 10 while(ch>'9' || ch<'0')ch=getchar(); 11 while(ch>='0' && ch<='9')str=str*10+ch-48,ch=getchar(); 12 return str; 13 } 14 int n,m,k,w[N],head[N],num=1,id[N]; 15 struct Lin{ 16 int next,to,dis; 17 }a[M<<1]; 18 void init(int x,int y,int z){ 19 a[++num].next=head[x]; 20 a[num].to=y; 21 a[num].dis=z; 22 head[x]=num; 23 } 24 bool mark[N][1<<Z];int ans=0; 25 void dfs(int x,int p,int tot) 26 { 27 if(mark[x][p])return ; 28 mark[x][p]=true; 29 if(x==1 && tot>=ans) 30 { 31 if(w[1] && !(p&(1<<(id[1]-1))))ans=tot+1; 32 else ans=tot; 33 } 34 int u; 35 for(int i=head[x];i;i=a[i].next) 36 { 37 u=a[i].to; 38 if(tot>a[i].dis)continue; 39 dfs(u,p,tot); 40 if(p&(1<<(id[x]-1)))continue; 41 if(w[x] && tot<a[i].dis)dfs(u,p|(1<<(id[x]-1)),tot+1); 42 } 43 } 44 int main() 45 { 46 int x,y,z; 47 n=gi();m=gi();k=gi(); 48 for(int i=1;i<=k;i++)x=gi(),w[x]=1,id[x]=i; 49 for(int i=1;i<=m;i++) 50 { 51 x=gi();y=gi();z=gi(); 52 init(x,y,z);init(y,x,z); 53 } 54 dfs(1,0,0); 55 printf("%d",ans); 56 return 0; 57 }