zoj 3644(dp + 记忆化搜索)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4834

思路:dp[i][j]表示当前节点在i,分数为j的路径条数,从题中可以得出,要在N处的分数为K,那么那些到达N的路径上的节点的val必然是K的因子,由于K的范围为[1, 1000000],二维数组开不下,那么我们可以用一个数组来保留K的所有因子,在用一个数组来保留这个因子的值,这样,二维数组就可开了,于是,就是记忆化搜索了!

 1 /*************************************************************************
 2     > File Name: zoj3644.cpp
 3     > Author: syhjh
 4     > Created Time: 2014年03月18日 星期二 20时47分15秒
 5  ************************************************************************/
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 #include <algorithm>
10 using namespace std;
11 
12 const int MAXN = (2000 + 20);
13 const int MAXM = (200000 + 200);
14 const int MAX = (1000000 + 100);
15 const int MOD = (1000000007);
16 template < class T > inline T GCD(T a, T b)
17 {
18     return b == 0 ? a : GCD(b, a % b);
19 }
20 
21 template < class T > inline T LCM(T a, T b)
22 {
23     return a / GCD(a, b) * b;
24 }
25 
26 
27 struct Edge {
28     int v, next;
29 } edge[MAXM];
30 
31 int N, M, K, val[MAXN];
32 int NE, head[MAXN];
33 
34 void Insert(int u, int v)
35 {
36     edge[NE].v = v;
37     edge[NE].next = head[u];
38     head[u] = NE++;
39 }
40 
41 int dp[MAXN][MAXN];
42 int pp[MAX], num[MAXN];
43 
44 void Init()
45 {
46     memset(pp, -1, sizeof(pp));
47     int cnt = 0;
48     for (int i = 1; i <= K; i++) {
49         if (K % i == 0) {
50             pp[i] = cnt;
51             num[cnt++] = i;
52         }
53     }
54 }
55 
56 int getDp(int u, int s)
57 {
58     if (s == -1) return 0;
59     if (u == N && num[s] == K) {
60         return 1;
61     }
62     if (dp[u][s] != - 1) return dp[u][s];
63     int ans = 0;
64     for (int i = head[u]; i != -1; i = edge[i].next) {
65         int v = edge[i].v;
66         if (K % val[v]) continue;
67         int tmp = LCM(num[s], val[v]);
68         if (tmp != num[s] && K % tmp == 0) {
69             ans += getDp(v, pp[tmp]);
70             ans %= MOD;
71         }
72     }
73     return dp[u][s] = ans;
74 }
75 
76 int main()
77 {
78     while (cin >> N >> M >> K) {
79         NE = 0;
80         memset(head, -1, sizeof(head));
81         while (M--) {
82             int u, v;
83             cin >> u >> v;
84             Insert(u, v);
85         }
86         for (int i = 1; i <= N; i++) {
87             cin >> val[i];
88         }
89         Init();
90         memset(dp, -1, sizeof(dp));
91         cout << getDp(1, pp[val[1]]) << endl;
92     }
93     return 0;
94 }
View Code

 

posted @ 2014-03-18 22:12  ihge2k  阅读(385)  评论(0编辑  收藏  举报