HDU 2452 Navy maneuvers (记忆化搜索)

来源:互联网 发布:sql语句查询重复数据 编辑:程序博客网 时间:2024/06/02 19:23

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2452

题意:给出一个图,n个点,m条边,保证无环,每个点有一个权值。指定一个点作为起点,Victory和Glory轮流选择下一个走到的点,将走过的点的权值相加,走到不能再向前为止。如果它们都选最用策略,问Victory能不能使权值和大于等于f,如果可以则Victory赢,否则Glory赢。

思路:

记忆化搜索,以u为起点时,Victory希望权值和dp[u]最大,Glory希望dp[u]最小。

用二维数组,dp[0][u]表示以u为起点能取得的最小值,dp[1][u]为能取得的最大和。

因为Victory和Glory轮流选择路线,所以有如下转移方程:

dp[0][u] = min{dp[1][v] + a[u], dp[0][u]}

dp[1][u] = max{dp[0][v] + a[u], dp[1][u]}

#include <stdio.h>#include <string.h>#include <algorithm>#include <math.h>#include <stdlib.h>#define INF 0x7fffffff#define MOD 1000000007#include <vector>using namespace std;typedef long long ll;const int MAXN = 10005;int n, m, f, s;int in[MAXN], a[MAXN], dp[5][MAXN];vector<int> G[MAXN];void dfs(int u){    if(dp[0][u] >= 0) return;    if(!G[u].size())    {        dp[0][u] = dp[1][u] = a[u];        return;    }    dp[0][u] = INF; dp[1][u] = 0;    for(int i = 0; i < G[u].size(); i++)    {        int v = G[u][i];        dfs(v);        dp[0][u] = min(a[u] + dp[1][v], dp[0][u]);        dp[1][u] = max(a[u] + dp[0][v], dp[1][u]);    }}int main(){    #ifdef LOCAL    freopen("data.in", "r", stdin);    #endif    int u, v;    while(~scanf("%d%d%d", &n, &m, &f))    {        for(int i = 1; i <= n; i++)        {            scanf("%d", &a[i]);            G[i].clear();        }        memset(in, 0, sizeof(in));        for(int i = 0; i < m; i++)        {            scanf("%d%d", &u, &v);            G[u].push_back(v);            in[v]++;        }        for(int i = 1; i <= n; i++)            if(!in[i])            {                s = i; break;            }        memset(dp, -1, sizeof(dp));        dfs(s);        if(dp[1][s] >= f)            printf("Victory\n");        else            printf("Glory\n");    }    return 0;}


0 0
原创粉丝点击