题解 P4962 【朋也与光玉】

ouuan

2018-11-03 23:05:32

Solution

此题按题意搜索 / $dp$ 即可,但如果搜索必须记忆化(说不定有什么神奇的剪枝能过这道题吧...出题人不知道QAQ)。 题解把代码改好看一点就没有过审了..那我就详细讲一下递推而把记搜删掉好了,毕竟已经有记搜题解了,但还没有其它的递推题解。 用 $f_{u,i}$ 表示以 $u$ 为起点,$i$ 的第 $j$ 位为 $1$ 表示还没有收集 $j$ 号光玉(不包括 $u$ 号节点),的最短路径。 转移方程: $f_{u,i}=\min\{f_{v,i\ xor\ 1<<a_u}+w\}\ \forall(u,v,w)\in E$ 初始化: $f_{u,1<<a_u}=0$ 由于可能是稠密图,用邻接矩阵存边即可。 参考代码: ``` #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n,m,k,a[110],f[110][1<<13],g[110][110],ans=0x3f3f3f3f; int main() { int i,u,v; cin>>n>>m>>k; memset(g,0x3f,sizeof(g)); memset(f,0x3f,sizeof(f)); for (i=1;i<=n;++i) { cin>>a[i]; } for (i=1;i<=m;++i) { cin>>u>>v; cin>>g[u][v]; } for (i=1;i<=n;++i) { f[i][1<<a[i]]=0; } for (i=1;i<(1<<k);++i) { for (u=1;u<=n;++u) { for (v=1;v<=n;++v) { if (i&(1<<a[u])) { f[u][i]=min(f[u][i],f[v][i^(1<<a[u])]+g[u][v]); } } } } for (i=1;i<=n;++i) { ans=min(ans,f[i][(1<<k)-1]); } if (ans==0x3f3f3f3f) { cout<<"Ushio!"; } else { cout<<ans; } return 0; } ```