首页 > 代码库 > *HDU2254 矩阵乘法

*HDU2254 矩阵乘法

奥运

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2990    Accepted Submission(s): 761


Problem Description
北京迎来了第一个奥运会,我们的欢呼声响彻中国大地,所以今年的奥运金牌 day day up!
比尔盖兹坐上鸟巢里,手里摇着小纸扇,看的不亦乐乎,被俺们健儿的顽强拼搏的精神深深的感动了。反正我的钱也多的没地方放了,他对自己说,我自己也来举办一个奥运会,看谁的更火。不过他的奥运会很特别:
1 参加人员必须是中国人;
2 至少会加法运算(因为要计算本人获得的金牌数)
他知道中国有很多的名胜古迹,他知道自己在t1 到 t2天内不可能把所有的地方都玩遍,所以他决定指定两个地方v1,v2,如果参赛员能计算出在t1到t2天(包括t1,t2)内从v1到v2共有多少种走法(每条道路走需要花一天的时间,且不能在某个城市停留,且t1=0时的走法数为0),那么他就会获得相应数量的金牌,城市的总数<=30,两个城市间可以有多条道路
,每条都视为是不同的。
 

 

Input
本题多个case,每个case:
输入一个数字n表示有n条道路 0<n<10000
接下来n行每行读入两个数字 p1,p2 表示城市p1到p2有道路,并不表示p2到p1有道路 (0<=p1,p2<2^32)
输入一个数字k表示有k个参赛人员
接下来k行,每行读入四个数据v1,v2,t1,t2 (0<=t1,t2<10000)
 

 

Output
对于每组数据中的每个参赛人员输出一个整数表示他获得的金牌数(mod 2008)
 

 

Sample Input
6
1 2
1 3
2 3
3 2
3 1
2 1
3
1 2 0 0
1 2 1 100
4 8 3 50
 

 

Sample Output
0
1506
0
Source

HDOJ 2008 Summer Exercise(4)- Buffet Dinner

代码:

 1 /*
 2 构造邻接矩阵A,f[i][j]表示i到j的道路,A^n中的各个元素f[i][j]表示从i到j走n步有多少种方法,因此就是矩阵乘法
 3 A^t1,A^(t1+1)......A^t2;注意点数太大的用map离散化一下。
 4 */
 5 #include<iostream>
 6 #include<cstring>
 7 #include<cstdio>
 8 #include<map>
 9 #include<cmath>
10 using namespace std;
11 const int mod=2008;
12 const int maxn=35;
13 map<string,int>m;
14 struct Lu
15 {
16     int f[maxn][maxn];
17 }e,g[10004];
18 Lu solve(Lu x,Lu y,int n)
19 {
20     Lu z;
21     memset(z.f,0,sizeof(z.f));
22     for(int k=1;k<=n;k++)
23     {
24         for(int i=1;i<=n;i++)
25         {
26             if(!x.f[i][k]) continue;
27             for(int j=1;j<=n;j++)
28             {
29                 z.f[i][j]+=x.f[i][k]*y.f[k][j];
30                 z.f[i][j]%=mod;
31             }
32         }
33     }
34     return z;
35 }
36 int main()
37 {
38     int n;
39     while(~scanf("%d",&n))
40     {
41         m.clear();
42         char a[30],b[30],v1[30],v2[30];
43         int cnt=0;
44         memset(e.f,0,sizeof(e.f));
45         for(int i=0;i<n;i++)
46         {
47             scanf("%s%s",&a,&b);
48             if(m[a]==0) m[a]=++cnt;
49             if(m[b]==0) m[b]=++cnt;
50             e.f[m[a]][m[b]]++;
51         }
52         memset(g[0].f,0,sizeof(g[0].f));
53         for(int i=1;i<=cnt;i++)
54             g[0].f[i][i]=1;
55         for(int i=1;i<=10001;i++)
56             g[i]=solve(g[i-1],e,cnt);
57         int k,t1,t2;
58         scanf("%d",&k);
59         while(k--)
60         {
61             scanf("%s%s%d%d",v1,v2,&t1,&t2);
62             if(m[v1]==0||m[v2]==0||t2==0)
63                 printf("0\n");
64             else
65             {
66                // if(t1>t2) swap(t1,t2);
67                 int ans=0;
68                 for(int i=t1;i<=t2;i++){
69                     if(i==0) continue;
70                     ans=(ans+g[i].f[m[v1]][m[v2]])%mod;
71                 }
72                 printf("%d\n",ans);
73             }
74         }
75     }
76     return 0;
77 }

 

*HDU2254 矩阵乘法