2015-04-01 20:25:02

思路:好题!

  题意可以转化为:两个人从起点到终点(两人的路径不能有交点),仅能从左向右走,求最多能经过多少点。

  方法1:DP:

    想了很久... 基本可以想到用dp[i][j]来表示一人走到 i ,另一人走到 j 能经过的最多点数。但是转移方程怎么想都难以避免重复...

    看了别人的博客,发现一个很巧妙的方法。

    首先发现,dp[i][j] = dp[j][i](两个人可以换位置),dp[i][j] = max{dp[i][k]} (1<=k<j , k与j有边相连)

    关于如何避免重复,我思考良久... 结果还是不太清晰。在转移方程时保证:j > i ,这样如果dp[i][k]的路径没有重复点,dp[i][j]的路径也不可能有重复点。

    (这种转移方法每次只走一个人,而且走的是走完之后更右边的那个人。j > i)

  方法2:网络流:

    并没有想到这种做法... 百度了才知道还能用网络流做。

    将每个点拆点(i 拆成 ia , ib),ia -> ib 建立容量为1,费用为1的边。为了实现两个走的条件,给起点1a->1b的边容量设为2,终点na->nb的边容量设为2。

    然后根据题目的输入给点之间建立边,要注意建边条件:从左到右(当时这里坑了...)

    最后跑一遍最大费用最大流,如果流量<2,那么答案就为1。否则输出费用即可。

 

DP:

 1 /*
 2 ID:naturec1
 3 PROG: tour
 4 LANG: C++
 5 */
 6 #include <cstdio>
 7 #include <cstring>
 8 #include <cstdlib>
 9 #include <cmath>
10 #include <vector>
11 #include <map>
12 #include <set>
13 #include <stack>
14 #include <queue>
15 #include <string>
16 #include <iostream>
17 #include <algorithm>
18 using namespace std;
19 
20 #define MEM(a,b) memset(a,b,sizeof(a))
21 #define REP(i,n) for(int i=0;i<(n);++i)
22 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
23 #define getmid(l,r) ((l) + ((r) - (l)) / 2)
24 #define MP(a,b) make_pair(a,b)
25 
26 typedef long long ll;
27 typedef pair<int,int> pii;
28 const int INF = (1 << 30) - 1;
29 const int MAXN = 110;
30 
31 int N,M,ans;
32 bool g[MAXN][MAXN];
33 int dp[MAXN][MAXN];
34 map<string,int> mp;
35 
36 int main(){
37     freopen("tour.in","r",stdin);
38     freopen("tour.out","w",stdout);
39     string str1,str2;
40     scanf("%d%d",&N,&M);
41     REP(i,N){
42         cin >> str1;
43         mp[str1] = i + 1;
44     }
45     REP(i,M){
46         cin >> str1 >> str2;
47         int id1 = mp[str1];
48         int id2 = mp[str2];
49         g[id1][id2] = g[id2][id1] = true;
50     }
51     dp[1][1] = 1;
52     for(int i = 1; i <= N; ++i){
53         for(int j = i + 1; j <= N; ++j){
54             dp[i][j] = -INF;
55             for(int k = 1; k < j; ++k) if(g[k][j] && dp[i][k] > 0){
56                 dp[i][j] = max(dp[i][j],dp[i][k] + 1);
57             }
58             dp[j][i] = dp[i][j];
59         }
60     }
61     int ans = 1;
62     for(int i = 1; i <= N; ++i) if(g[i][N]){
63         ans = max(ans,dp[i][N]);
64     }
65     printf("%d\n",ans);
66     return 0;
67 }
View Code

相关文章:

  • 2021-06-16
  • 2022-12-23
  • 2021-09-29
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-10-21
  • 2021-11-04
猜你喜欢
  • 2021-07-06
  • 2021-11-07
  • 2021-11-07
  • 2021-05-30
  • 2021-07-13
  • 2022-02-24
  • 2022-02-16
相关资源
相似解决方案