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的所有因子,在用一个数组来保留这个因子的值,这样,二维数组就可开了,于是,就是记忆化搜索了!

zoj 3644(dp + 记忆化搜索)
 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

 

你可能感兴趣的:(ZOJ)