您的位置:首页 > 大数据 > 人工智能

POJ 3735 Training little cats(矩阵乘法 + 稀疏矩阵优化)——2016弱校联盟十一专场10.7(12点场)

2016-10-07 18:32 489 查看
传送门

Training little cats

Time Limit: 2000MSMemory Limit: 65536K
Total Submissions: 13373Accepted: 3298
Description
Facer’s pet cat just gave birth to a brood of little cats. Having considered the health of those lovely cats, Facer decides to make the cats to do some exercises. Facer has well designed a set of moves for his cats. He is now asking you to supervise the cats to do his exercises. Facer’s great exercise for cats contains three different moves:
g i : Let the ith cat take a peanut.
e i : Let the ith cat eat all peanuts it have.
s i j : Let the ith cat and jth cat exchange their peanuts.
All the cats perform a sequence of these moves and must repeat it m times! Poor cats! Only Facer can come up with such embarrassing idea.
You have to determine the final number of peanuts each cat have, and directly give them the exact quantity in order to save them.
InputThe input file consists of multiple test cases, ending with three zeroes “0 0 0”. For each test case, three integers n, m and k are given firstly, where n is the number of cats and k is the length of the move sequence. The following k lines describe the sequence.
(m≤1,000,000,000, n≤100, k≤100)
OutputFor each test case, output n numbers in a single line, representing the numbers of peanuts the cats have.
Sample Input3 1 6

g 1

g 2

g 2

s 1 2

g 3

e 2

0 0 0Sample Output2 0 1

题目大意:

有 n(n≤100) 只小猫,现在有 3 种操作:

1): g−i 表示的是给 第 i 只小猫一个花生;

2): e−i 表示的是第 i 只小猫吃完了所有的花生

3): s−i j 表示的是第 i 只小猫跟第 j 只小猫的花生交换一下。

现在有 k(k≤100) 种操作,然后执行 m(≤109) 次,求最终的每只小猫拥有的花生的数量。

解题思路:

因为其中的 m 特别大,所以就可以联想到用矩阵乘法来优化,然后怎么构造这个矩阵呢?我们就拿样例来说把,现在三只小猫拥有的花生的

数量分别是 {x,y,z} 那么经过 g−1 操作之后就变成了 {x+1,y,z} 所以我们设一个 (n+1)∗(n+1)(之所以不设 n∗n 的矩阵是因为没

有办法操作) 的矩阵,所以将 {x+1,y,z} 加上一维变成 {x+1,y,z,1} 那么现在这个 (n+1)∗(n+1) 的矩阵就变成了 1001010000100001

以此类推可以得到 g−2 和 g−3 的矩阵(没出现一个 g−i ,就将构造的矩阵 P[n−1][i−1]++),现在再来观察一下 s−i j ,那么我们

就交换对应的两列就行,e−i就将第 i−1 列清空。然后矩阵快速幂一下,注意这里的矩阵乘法是稀疏矩阵的乘法,就是特判一下零的情况。

My Code:

#include <iostream>
#include <cstdio>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const LL MAXN = 1e2+5;
typedef struct{
LL mat[MAXN][MAXN];
} Matrix;
Matrix P, I;
LL n, m, k;
Matrix Multi_Matrix(Matrix a, Matrix b){
Matrix c;
memset(c.mat, 0, sizeof(c.mat));
for(LL i=0; i<n; i++)
for(LL j=0; j<n; j++)
if(a.mat[i][j])
for(LL k=0; k<n; k++)
c.mat[i][k] += a.mat[i][j] * b.mat[j][k];
return c;
}

Matrix Pow_Matrix(LL b){
Matrix ans = I, B = P;
while(b){
if(b & 1)
ans = Multi_Matrix(ans, B);
b>>=1;
B = Multi_Matrix(B, B);
}
return ans;
}
void Debug(Matrix a){
for(LL i=0; i<n; i++){
for(LL j=0; j<n; j++)
cout<<a.mat[i][j]<<" ";
cout<<endl;
}
}
int main()
{
while(~scanf("%lld%lld%lld",&n,&m,&k)){
if(!n && !m && !k)
break;
n++;
memset(I.mat, 0, sizeof(I.mat));
for(LL i=0; i<n; i++)
I.mat[i][i] = 1;
memset(P.mat, 0, sizeof(P.mat));
for(LL i=0; i<n; i++)
P.mat[i][i] = 1;
while(k--){
LL x, y;
char ch;
getchar();
scanf("%c",&ch);
if(ch == 'g'){
scanf("%lld",&x);
P.mat[n-1][x-1]++;
}
else if(ch == 's'){
scanf("%lld%lld",&x,&y);
for(LL i=0; i<n; i++)
swap(P.mat[i][x-1], P.mat[i][y-1]);
}
else{
scanf("%lld",&x);
for(LL i=0; i<n; i++)
P.mat[i][x-1] = 0;
}
}
///Debug(P);
Matrix ans = Pow_Matrix(m);
for(LL i=0; i<n-1; i++){
if(i == n-2)
printf("%lld\n",ans.mat[n-1][i]);
else
printf("%lld ",ans.mat[n-1][i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: