POJ3249 Test for Job

今天写了4h的test for job,之所以用了这么长时间是因为一开始的方法出现了问题。
这道题目如果按照一般的动规思想,会想到从下往上的解决方法,也就是从目标城市网上搜索ans[i-1]=max(ans[i-1],ans[i]+value[i-1])的方式进行动规,但是这种方法会有特别极端的情况导致计算量激增。如下图所示。
如果从下往上搜索,很明显,这一条曲曲折折的线条被重复计算了5次,如果底下的分支很大,那么计算量就会增长很快。
这里写图片描述
所以我们必须采取从上向下的记忆化搜索方式。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int INF = -0x3fffffff;
long long int max(long long int a, long long int b)
{
    if (a > b) return a;
    return b;
}
struct city
{
    int value;
    bool first;//记录是不是第一个
};city citys[100005];
vector<int> vnext[100005];//记录城市i的后续城市
int ans[100005];//数组的下标代表城市编号i,代表i到target的最大价值
int search(int k)//自上而下的记忆化搜索
{
    if (ans[k] != INF) return ans[k];
    if (vnext[k].empty()) return citys[k].value;//如果是最后一个
    for (int i = 0; i < vnext[k].size(); ++i)
        ans[k] = max(ans[k], search(vnext[k][i]) + citys[k].value);
    return ans[k];
}
int main()
{
    int city_num = 0, road_num = 0;
    while (cin >> city_num >> road_num)
    {
        for (int i = 1; i <= city_num; ++i)
        {
            scanf("%d", &citys[i].value);
            vnext[i].clear();
            ans[i] = INF;
            citys[i].first = true;
        }
        int tmp1 = 0, tmp2 = 0;
        for (int i = 0; i < road_num; ++i)
        {
            scanf("%d%d", &tmp1, &tmp2);
            vnext[tmp1].push_back(tmp2);
            citys[tmp2].first = false;
        }
        int MAX = INF;
        for (int i = 1; i <= city_num; ++i)
        {
            if (citys[i].first)//从起始城市开始向下递归
                MAX = max(MAX, search(i));
        }
        printf("%d\n", MAX);
    }
    return 0;
}

如有错误,希望大家纠正!

猜你喜欢

转载自blog.csdn.net/holmosaint/article/details/72773944
job