地址:http://acm.uestc.edu.cn/#/problem/show/1588
题目:复制过来发现有问题,自己去cdoj看吧
思路:
1.先进行多次spfa跑出所有人之间的相互到达所需要的步数。
2.知道所有人之间的距离关系后,就是个从初始点出发泡q个妹子所需要的最少花费问题。
这时你可以全排列求解:O(q!)
或者状压dp:dp[s][x]可以转移到dp[s|(1<<k)],x可到达k。时间复杂度O((q^2)*(2^q));
1 #include <bits/stdc++.h>
2
3 using namespace std;
4
5 #define MP make_pair
6 #define PB push_back
7 typedef long long LL;
8 typedef pair<int,int> PII;
9 const double eps=1e-8;
10 const double pi=acos(-1.0);
11 const int K=1e6+7;
12 const int mod=554056561;
13
14
15 struct node
16 {
17 int x,y,v;
18 node(){}
19 node(int a,int b,int c){x=a,y=b,v=c;}
20 }gg[10];
21 int d[100][100],dp[1<<10][10];
22 int n,m,s,q,dis[100][100],inque[100][100];
23 int dx[]={-2,-2,-1,-1,1,1,2,2};
24 int dy[]={-1,1,-2,2,-2,2,-1,1};
25
26 void bfs(node &ta)
27 {
28 queue<node>q;
29 memset(dis,0x3f3f3f3f,sizeof dis);
30 memset(inque,0,sizeof inque);
31 q.push(ta),dis[ta.x][ta.y]=0,inque[ta.x][ta.y]=1;
32 while(q.size())
33 {
34 node x=q.front();
35 q.pop(),inque[x.x][x.y]=0;
36 for(int i=0;i<8;i++)
37 {
38 int nx=x.x+dx[i],ny=x.y+dy[i];
39 if(!(nx>=1 && ny>=1 && nx<=n && ny<=m))
40 continue;
41 if(dis[nx][ny]>dis[x.x][x.y]+abs(dx[i]))
42 {
43 dis[nx][ny]=dis[x.x][x.y]+abs(dx[i]);
44 if(!inque[nx][ny])
45 q.push(node(nx,ny,0)),inque[nx][ny]=1;
46 }
47 }
48 }
49 }
50 int main(void)
51 {
52 std::ios::sync_with_stdio(false);
53 std::cin.tie(0);
54 int t;
55 cin>>t;
56 while(t--)
57 {
58 int ans=0x3f3f3f3f;
59 cin>>n>>m>>s>>q>>gg[0].x>>gg[0].y;
60 for(int i=1; i<=s; i++)
61 cin>>gg[i].x>>gg[i].y>>gg[i].v;
62 for(int i=0;i<=s;i++)
63 {
64 bfs(gg[i]);
65 for(int j=0;j<=s;j++)
66 d[i][j]=dis[gg[j].x][gg[j].y];
67 //printf("d[%d][%d]:%d
",i,j,d[i][j]);
68 }
69 memset(dp,0x3f3f3f3f,sizeof dp);
70 for(int i=1;i<=s;i++)
71 dp[1<<(i-1)][i]=d[0][i]+gg[i].v;
72 for(int i=0,sz=(1<<s);i<sz;i++)
73 {
74 for(int j=0;j<s;j++)
75 for(int k=0;k<s;k++)
76 if(((1<<j)^i) && ((1<<k)&i))
77 dp[i|(1<<j)][j+1]=min(dp[i][k+1]+d[k+1][j+1]+gg[j+1].v,dp[i|(1<<j)][j+1]);
78 }
79 for(int i=0,sz=(1<<s);i<sz;i++)
80 for(int j=1;j<=s;j++)
81 {
82 int sum=0;
83 for(int k=0;k<s;k++)
84 if(i&(1<<k)) sum++;
85 if(sum==q)ans=min(ans,dp[i][j]);
86 }
87 if(ans>=0x3f3f3f3f)
88 ans=-1;
89 cout<<ans<<"
";
90 }
91 return 0;
92 }