题解 P2747 【[USACO5.4]周游加拿大Canada Tour】
一道基础的dp
把返回的路线反向,那么整条路线就变成了两条不相交的从起点到终点的路线。这样我们可以用DP解决。
状态设定
f[i,j] 为假定的甲乙两人,甲走到第i个城市,乙走到第j个城市时,两人走过的城市数目的和。
初始状态
f[1,1]=1
状态转移方程
f[j,i]=f[i,j]=max{f[i,k]+1}(k到j存在飞机航线,以及f[i,k]>0,就是说存在f[i,k]的走法,1<=k<j,i<j<=n
交换甲乙,则肯定有f[j,i]=f[i,j]。
目标结果
由于题中告知必须走到终点才能返回,输出结果一定是max{f[i,N]}(i到N存在飞机航线)。 如果没有经过城市数目大于1的可行目标状态,则无法完成这次环游,输出1。
#include <cstdio>
#include <string>
#include <map>
#include <iostream>
#include <cstring>
using namespace std;
string s,s1,s2;
int n,m,f[110][110],a[110][110];
map <string,int> ma;
main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
cin>>s;
ma[s]=i;
}
for (int i=1;i<=m;i++)
{
cin>>s1>>s2;
a[ma[s1]][ma[s2]]=1;
a[ma[s2]][ma[s1]]=1;
//printf("%d %d\n",ma[s1],ma[s2]);
}
//memset(f,-1,sizeof f);
f[1][1]=1;
for (int i=1;i<n;i++)
for (int j=i+1;j<=n;j++)
{
for (int k=1;k<j;k++)
if (a[j][k]&&f[i][k])
f[i][j]=max(f[i][j],f[i][k]+1);
f[j][i]=f[i][j];
}
int ans=1;
for (int i=1;i<=n;i++)
if(a[i][n])
ans=max(ans,f[i][n]);
printf("%d",ans);
}