区域赛的题目读着就是蛋疼,读到一半放弃了,不过今天重新拾起。
题意:有一个有向无自环的连通图,每个结点都有权值。现在有两艘船要从能到达任意结点的点出发(我的理解就是入度为零的点),直到出度为零的点,途中获得每个结点的权值(包括起点和终点)。现在这两艘船a希望得到更多的权值,另一艘b希望得到尽量少的权值。他们从起点开始,由a,b轮流领航(自然领航的人会走对自己有利的路),问到终点的权值能否满足要求。
思路:如果只有一艘船,那这个问题简化成如何获得更多或更少的权值,这类型的记忆化搜索做过一些。两艘船的话,用dp[i][0]表示船b以i为根结点最少能获得的权值;dp[i][1]表示船a以i为根结点最多能够获得的权值。。。 此时dp[i][] = v[i] + max(dp[u0][]..,.,.,.,..dp[un][]); 或者dp[i][] = v[i] + min(dp[u0][]..,.,.,.,..dp[un][]); 只需要用标记判断是谁在领航就行。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
# define MAX 11111
using namespace std;
int dp[MAX][2],v[MAX],deg[MAX];
int n,m,f;
vector <int> edge[MAX];
void init() {
memset(dp,0,sizeof(dp));
memset(deg,0,sizeof(deg));
for(int i=0; i<=11111; i++) {
edge[i].clear();
}
}
int dfs(int v0,int cur) {
if(dp[v0][cur%2] != 0) return dp[v0][cur%2];
int size = edge[v0].size();
if(size == 0) return v[v0];
int maxx = -1111111111,minn = 1111111111;
for(int i=0; i<size; i++) {
int u = edge[v0][i];
if(cur % 2 == 1) {
maxx = max(maxx,dfs(u,cur+1));
}
else {
minn = min(minn,dfs(u,cur+1));
}
}
if(cur % 2 == 1) return dp[v0][cur%2] = maxx + v[v0];
else return dp[v0][cur%2] = minn + v[v0];
}
int main() {
int i,a,b;
while(scanf("%d%d%d",&n,&m,&f)!= EOF) {
init();
for(i=1; i<=n; i++) scanf("%d",&v[i]);
for(i=1; i<=m; i++) {
scanf("%d%d",&a,&b);
edge[a].push_back(b);
deg[b] ++;
}
int maxx = -1111111111;
for(i=1; i<=n; i++) {
if(! deg[i]) {
maxx = max(maxx,dfs(i,1));
}
}
if(maxx >= f) printf("Victory\n");
else printf("Glory\n");
}
return 0;
}