ZOJ3352 Boring Board Game

Boring Board Game

Time Limit: 2 Seconds      Memory Limit: 65536 KB

You know, when Lanrete and DD are together, they are always playing boring board games. And they invent the games themselves! Here is yet another boring board games between Lanrete and DD.

They play this game on a directed acyclic graph with N vertices numbered from 0 to N-1 (1 <= N <= 50). For each vertex, their is a digit on it, the digit will be 0, 1, or 2. There are also two flags, a white one and a black one, on the vertices of the graph, initially in vertex X and Y.

Initially, they say the loser should give the winner 1 dollar, but the amount of dollars the loser should give will change during the game. In the game, they move the flag in turn. For each move, the player should choose one flag, and move it to another vertex along an edge in the graph. Say the digit on the destination vertex is d. If it's the white flag the player moved, the amount of dollars the loser should give will be increased by d, otherwise the amount will be decreased by d. If the player cannot find a legal move, she/he loses the game and should give the winner dollars. But actually the final amount of dollars can be negative, that means it's the loser of the game will actually win money!

Lanrete will move the flag at first. Assume both Lanrete and DD are very smart, how many dollars Lanrete can get at most? Note that can be a negative amount of dollars.

Input

There are multiple cases. For each case:

First line, four integers N, M, X, Y.

Second line, N integers, indicating the digit on vertex 0 to N-1.

The next M line, each has two numbers a and b, indicating the start and destination vertices of an edge.

Output

For each test case, output the amount of dollars Lanrete will get at last, and the number of different ways she can move the flag on the first move in order to get that amount of money.

Sample Input

4 5 2 0
0 2 2 1
0 1
0 2
1 2
1 3
2 3

Sample Output

-1 3
原题地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3352
_______________________________________________________________________________________________________
题解:
博弈问题,不是很会,基本是照着标程写的。
 

记录dp[i][j][k]表示白旗在i,黑旗在j,当前赌注为k的最大收益,因为是有向无环图,所以状态不会有环。

于是直接记忆化搜索就好了,每次枚举白旗的移动或黑旗的移动取最大值,如果不能移动,那么就是-k。时间复杂度O(n^4),空间复杂度O(n^3)


代码
1 #include<stdio.h>
2 #include<memory.h>
3 #define inf 0xfffffff
4 int dp[52][52][204],count[52][52][204];
5 int n,m,x,y,a,b,t,i;
6 int head[52],next[3000],node[3000],v[52];
7 void solve(int x,int y,int z)
8 {
9 int temp,ret,cnt,i;
10 if (count[x][y][100+z]!=-1)//赢的钱有可能是负数,+100变成正的
11 return;
12 ret=(head[x]==-1&&head[y]==-1)? -z:-inf;//若无路可走,则输,赔钱
13 cnt=1;
14 for (i=head[x];i!=-1;i=next[i])//移动白旗
15 {
16 solve(node[i],y,z+v[node[i]]);
17 temp=-dp[node[i]][y][100+z+v[node[i]]];//负号:走了一轮,赢;两轮,输;三轮,赢;四轮输……一次类推
18 if (temp>ret)
19 {
20 ret=temp;
21 cnt=1;
22 }
23 else if (temp==ret)
24 cnt++;
25 }
26 for (i=head[y];i!=-1;i=next[i])//移动黑棋
27 {
28 solve(x,node[i],z-v[node[i]]);
29 temp=-dp[x][node[i]][100+z-v[node[i]]];
30 if (temp>ret)
31 {
32 ret=temp;
33 cnt=1;
34 }
35 else if (temp==ret)
36 cnt++;
37 }
38 dp[x][y][100+z]=ret;//表示白旗在X,黑棋在Y,当前赔钱数为Z时的最大收益
39 count[x][y][100+z]=cnt;//记录方案总数
40 }
41 void init()
42 {
43 while (scanf("%d%d%d%d",&n,&m,&x,&y)!=EOF)
44 {
45 for (i=0;i<n;i++)
46 scanf("%d",&v[i]);
47 memset(head, 0xff, sizeof(head));
48 memset(next, 0xff, sizeof(next));
49 t=0;
50 for (i=1;i<=m;i++)
51 {
52 scanf("%d%d",&a,&b);
53 next[++t]=head[a];
54 head[a]=t;
55 node[t]=b;
56 }
57 memset(count, 0xff, sizeof(count));
58 solve(x,y,1);
59 printf("%d %d\n",dp[x][y][101],count[x][y][101]);
60 }
61 }
62 int main()
63 {
64 init();
65 return 0;
66 }
67

 

posted on 2010-07-28 14:51  风也轻云也淡  阅读(242)  评论(0编辑  收藏  举报