2010-1074

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

by 猛犸也钻地

解题报告:

{{{
一道博弈题,题目说是个有向无环图,因此可以直接用记忆化做,不用考虑后效性了。

玩家要移动白旗和黑旗,自然在记录状态的数组中要有这两个,另外还要有当前的赌注,这会影响到决策,
用f[x][y][s+100]表示白旗在x点,黑旗在y点,当前赌注为s时的最多能赢的钱,s在[-100,100]内所以要+100。

记忆化搜索时,先把当前的f为-INF,如果有路可走,必然能更新到一个大于-INF的数,
把所有边都访问完了后发现f还是-INF,说明无路可走了,把f设成-s

另外,求出发路径数只要对起点连出的边看一遍就行了。
}}}


代码:

{{{
#!cpp
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int INF = 1000000;

vector<int> e[50];
int f[50][50][201],d[50];

int calc(int x, int y, int s){
    if(f[x][y][s+100]>-INF) return f[x][y][s+100];
    for(int i=0;i<e[x].size();i++){
        int v=-calc(e[x][i],y,s+d[e[x][i]]);
        if(v>f[x][y][s+100]) f[x][y][s+100]=v;
    }
    for(int i=0;i<e[y].size();i++){
        int v=-calc(x,e[y][i],s-d[e[y][i]]);
        if(v>f[x][y][s+100]) f[x][y][s+100]=v;
    }
    if(f[x][y][s+100]<=-INF) f[x][y][s+100]=-s;
    return f[x][y][s+100];
}

int main(){
    int n,m,x,y;
    while(scanf("%d%d%d%d",&n,&m,&x,&y)>0){
        memset(f,192,sizeof(f));
        for(int i=0;i<n;i++){
            scanf("%d",&d[i]);
            e[i]=vector<int>();
        }
        for(int i=0;i<m;i++){
            int p,q;
            scanf("%d%d",&p,&q);
            e[p].push_back(q);
        }
        printf("%d ",calc(x,y,1));
        int sum=0;
        for(int i=0;i<e[x].size();i++){
            int v=-calc(e[x][i],y,1+d[e[x][i]]);
            if(v==f[x][y][101]) sum++;
        }
        for(int i=0;i<e[y].size();i++){
            int v=-calc(x,e[y][i],1-d[e[y][i]]);
            if(v==f[x][y][101]) sum++;
        }
        if(!sum) sum=1;
        printf("%d\n",sum);
    }
}
}}}

by 猛犸也钻地

解题报告:

一道博弈题,题目说是个有向无环图,因此可以直接用记忆化做,不用考虑后效性了。
玩家要移动白旗和黑旗,自然在记录状态的数组中要有这两个,另外还要有当前的赌注,这会影响到决策,
用f[x][y][s+100]表示白旗在x点,黑旗在y点,当前赌注为s时的最多能赢的钱,s在[-100,100]内所以要+100。
记忆化搜索时,先把当前的f为-INF,如果有路可走,必然能更新到一个大于-INF的数,
把所有边都访问完了后发现f还是-INF,说明无路可走了,把f设成-s
另外,求出发路径数只要对起点连出的边看一遍就行了。

代码:

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int INF = 1000000;
vector<int> e[50];
int f[50][50][201],d[50];
int calc(int x, int y, int s){
    if(f[x][y][s+100]>-INF) return f[x][y][s+100];
    for(int i=0;i<e[x].size();i++){
        int v=-calc(e[x][i],y,s+d[e[x][i]]);
        if(v>f[x][y][s+100]) f[x][y][s+100]=v;
    }
    for(int i=0;i<e[y].size();i++){
        int v=-calc(x,e[y][i],s-d[e[y][i]]);
        if(v>f[x][y][s+100]) f[x][y][s+100]=v;
    }
    if(f[x][y][s+100]<=-INF) f[x][y][s+100]=-s;
    return f[x][y][s+100];
}
int main(){
    int n,m,x,y;
    while(scanf("%d%d%d%d",&n,&m,&x,&y)>0){
        memset(f,192,sizeof(f));
        for(int i=0;i<n;i++){
            scanf("%d",&d[i]);
            e[i]=vector<int>();
        }
        for(int i=0;i<m;i++){
            int p,q;
            scanf("%d%d",&p,&q);
            e[p].push_back(q);
        }
        printf("%d ",calc(x,y,1));
        int sum=0;
        for(int i=0;i<e[x].size();i++){
            int v=-calc(e[x][i],y,1+d[e[x][i]]);
            if(v==f[x][y][101]) sum++;
        }
        for(int i=0;i<e[y].size();i++){
            int v=-calc(x,e[y][i],1-d[e[y][i]]);
            if(v==f[x][y][101]) sum++;
        }
        if(!sum) sum=1;
        printf("%d\n",sum);
    }
}