acm-星际旅行

来源:互联网 发布:淘宝店铺收藏在哪里 编辑:程序博客网 时间:2024/04/17 05:08

星际旅行

时间限制:20000 ms  内存限制:65535 KB
难度:5
描述

在半人马星系,有M*N个星球,它们排成了M行N列,每个星球与其上下左右的星球都有一条星际航道相连,每个星球从属于一个国家,同一个国家中的所有星球都可以通过使用星际之门相连在一起。

现在小渡想从坐标为(1,1)的星球(左上角)航行到坐标为(M,N)的星球,为了体验星际旅行的美妙感觉,他想使自己通过星际之门和通过航道的次数之和为P,现在问他有多少种旅行方法可以满足要求。输出结果对1000007取余。

(注意旅行次序相同的方案当成同一种方案)

输入
第一行输入一个整数T(T<=20)表示测试数据的组数
每组测试数据的第一行是三个整数M,N,P,分别表示星球有M行,N列,小渡想通过星际之门和通过航道的次数之和为P(1<=M,N<=10,P<=100000000)
随后是一个M行N列的矩阵,代表着该处星球所属国家的编号(编号不超过20)
输出
输出满足要求的旅行方案数
输出结果对1000007取余。
样例输入
12 2 31 1 1 1 
样例输出
7
来源
[张云聪]原创
代码:
#include
#include
#include
#define max 101
#define len 1000007
using namespace std;
typedef struct numb
{
 long long a[max][max]; 
}MT;
MT ans;
int m,n,p;
void mult(numb &x,numb y,numb z)
{
 memset(x.a,0,sizeof(x.a));
 for(int i=0;i
  for(int j=0;j
  {
   x.a[i][j]=0;
   for(ints=0;s
   {
    x.a[i][j]+=y.a[i][s]*z.a[s][j];
    
   x.a[i][j]%=len;
  }
}
int main()
{
 int t;
 scanf("%d",&t);
 while(t--)
 {
  scanf("%d%d%d",&m,&n,&p);
  int arry[max];
  memset(ans.a,0,sizeof(ans.a));
  memset(arry,0,sizeof(arry));
  for(int i=0;i
   scanf("%d",&arry[i]);
  for(int i=0;i
  {
   
   if(i/n-1>=0)
   {
    ans.a[i][i-n]=1;
    ans.a[i-n][i]=1; 
   }
   if(i/n+1
   {
    ans.a[i][i+n]=1;
    ans.a[i+n][i]=1; 
   }
   if(i%n+1
   {
    ans.a[i][i+1]=1;
    ans.a[i+1][i]=1; 
   }
   if(i%n-1>=0)
   {
    ans.a[i][i-1]=1;
    ans.a[i-1][i]=1;  
   }
   for(intj=i+1;j
    if(arry[i]==arry[j]) 
    {
     ans.a[i][j]=1;
     ans.a[j][i]=1; 
    
  }
  MT res;
  memset(res.a,0,sizeof(res.a));
  for(int i=0;i
   res.a[i][i]=1;
  while(p)
  {
   if(p&1)
    mult(res,res,ans);
   p>>=1;
   mult(ans,ans,ans);  
  }
  printf("%d\n",res.a[0][n*m-1]);
   
 }
 return 0;
}
原创粉丝点击