题目链接:https://vjudge.net/contest/152219#overview。
水题较多。就贴一下当时没做出来的几题好了。
D,方法很简单,当时没想出来。用pos[x]表示x这个数已经是递增序列的第几个了,那么每次输入一个数x,令pos[x] = pos[x-1] + 1并更新答案ans即可。(当然所有pos都要预先设为0)
H,记忆化搜索连样例都过不了= =,不知道为什么,觉得可能是因为一个点可以经过好几次的原因。参考了BH学长的方法,先floyd预处理出两两之间的距离,再暴力枚举需要访问点的顺序,维护最小值即可。代码如下:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <iostream> 5 #include <vector> 6 #include <queue> 7 using namespace std; 8 typedef long long ll; 9 const int N = 100 + 5; 10 typedef pair<int,int> pii; 11 const int inf = 0x3f3f3f3f; 12 13 int dis[N][N]; 14 int n,m,f; 15 int have[15]; 16 int id[15]; 17 void floyd() 18 { 19 for(int k=1;k<=n;k++) 20 { 21 for(int i=1;i<=n;i++) 22 { 23 for(int j=1;j<=n;j++) 24 { 25 dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); 26 } 27 } 28 } 29 } 30 31 int main() 32 { 33 int T; cin >> T; 34 int kase = 1; 35 while(T--) 36 { 37 scanf("%d%d%d",&n,&m,&f); 38 memset(dis,inf,sizeof dis); 39 for(int i=1;i<=n;i++) dis[i][i] = 0; 40 for(int i=1;i<=m;i++) 41 { 42 int u,v,w; 43 scanf("%d%d%d",&u,&v,&w); 44 dis[u][v] = dis[v][u] = w; 45 } 46 for(int i=1;i<=f;i++) scanf("%d",have+i), id[i] = i; 47 floyd(); 48 int ans = inf; 49 do 50 { 51 int sum = dis[1][have[id[1]]] + dis[have[id[f]]][n]; 52 for(int i=1;i<f;i++) sum += dis[have[id[i]]][have[id[i+1]]]; 53 ans = min(ans, sum); 54 }while(next_permutation(id+1,id+1+f)); 55 printf("Case %d: %d ",kase++,ans); 56 } 57 }
最后一题待补。