简单动态规划题,不过也可以用最短路之类算法来做。被题意坑了好久之后终于A掉了,也不知道是出题人英语水平太渣还是我英语太差。下面贡献标准完美中文题意:维维要去旅游,然后旅游公司表示有DIY线路,维维可以自己选线路去旅游,每个城市都有一定的兴趣点,维维想要在这次旅游中获得最多的兴趣点数,另外起点在杭州,终点也一定是在杭州,只是中途的城市以及路线要自己DIY,并且绝对不会有从大编号城市到小编号城市的路线(城市编号从1到N,另外N+1表示终点),显示输入测试组数,然后每组测试先是输入一个城市数量N(2<=N<=100,包括起点),然后依次是N个城市的兴趣点数,再输入路线数量,接下来每条路输入两个数A和B,表示有从A到B的路线。最后你要按照格式输出获得的最大兴趣点以及路线就是了。
我的解题思路:动态规划解法嘛,很明显就能推导出状态转移方程式,假设dp[i]表示到达i城市能够获得的最大兴趣点数,points[i]表示城市i的兴趣点数,那么dp[i] = max(dp[j] + points[i])其中1<=j<i并且前提是有从j到i的线路。因为只有可能是从小编号到大编号城市的路线,所以递推时肯定是从小到大了。至于路线嘛十分简单,我的方法是:给dp赋值时顺便存一下前一个城市的编号就行了,这样就可以从终点开始找沿途把城市编号存入栈中然后就可以输出路线了。
下面是我的解题代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <stack>
#include <algorithm>
using namespace std;
#define N 111
struct DP
{
int prev; //选择最优路线时该城市的上一个城市
int points; //选择最优路线时到达该城市积累的点数
};
int city[N]; //存储该城市的兴趣点
DP dp[N];
bool map[N][N]; //map[i][j]为true表示存在i到j的路线
int tn, cn, rn; //样例数,城市数和路线数
stack <int> s; //存储路线所用的栈
void Init(); //初始化
void Read(); //输入
void DataProcess(); //数据处理
int main()
{
scanf("%d", &tn);
for (int t=1; t<=tn; ++t)
{
Init();
Read();
printf("CASE %d#\n", t);
DataProcess();
if (t != tn) putchar('\n');
}
return 0;
}
void Init()
{
for (int i=1; i<N; ++i)
{
city[i] = 0;
dp[i].prev = 0;
dp[i].points = 0;
for (int j=1; j<N; ++j)
{
map[i][j] = false;
}
}
return;
}
void Read()
{
int a, b;
scanf("%d", &cn);
for (int i=1; i<=cn; ++i)
{
scanf("%d", &city[i]);
}
scanf("%d", &rn);
for (int i=0; i<rn; ++i)
{
scanf("%d %d", &a, &b);
map[a][b] = true;
}
return;
}
void DataProcess()
{
for (int i=1; i<=cn; ++i)
{
for (int j=1; j<=cn; ++j)
{
if (map[j][i] && dp[i].points < dp[j].points + city[i])
{
dp[i].points = dp[j].points + city[i];
dp[i].prev = j;
}
}
}
int maxpoints = 0;
int maxid = 0;
for (int i=1; i<=cn; ++i)
{
if (map[i][cn+1] && maxpoints < dp[i].points)
{
maxpoints = dp[i].points;
maxid = i;
}
}
printf("points : %d\n", maxpoints);
while (maxid != 0)
{
s.push(maxid);
maxid = dp[maxid].prev;
}
printf("circuit : ");
while (!s.empty())
{
printf("%d->", s.top());
s.pop();
}
printf("1\n");
return;
}