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 }