魔术棋子
题目描述 在一个M*N的魔术棋盘中,每个格子中均有一个整数,当棋子走进这个格子中,则此棋子上的数会被乘以此格子中的数。一个棋子从左上角走到右下角,只能向右或向下行动,请问此棋子走到右下角后,模(mod)K可以为几? 如以下2*3棋盘: 3 4 4 5 6 6 棋子初始数为1,开始从左上角进入棋盘,走到右下角,上图中,最后棋子上的数可能为288,432或540。所以当K = 5时,可求得最后的结果为:0,2,3。 输入输出格式 输入格式: 输入文件magic.in第一行为三个数,分别为M,N,K (1 ≤ M,N,K ≤ 100)以下M行,每行N个数,分别为此方阵中的数。 输出格式: 输出文件magic.out第一行为可能的结果个数 第二行为所有可能的结果(按升序输出) 输入输出样例 输入样例#1: 2 3 5 3 4 4 5 6 6 输出样例#1: 3 0 2 3
解:依然是搜索加剪枝
到达每个点的时候,会出现的重复情况是
到达那个点的乘积已经出现过并且被计入过答案
那么开一个布尔数组判重就行,
如果vis[x][y][p]出现过,直接返回上一层
#include<bits/stdc++.h> #define ll long long #define DB double using namespace std; int n,m,k,a[200][200]; bool v[120][120][120],use[200]; int ans[200*200],l,rx,ry; int dx[]={1,0},dy[]={0,1}; ll tmp; void dfs(int x,int y,int h) { if(v[x][y][h]) return; // cout<<x<<" "<<y<<" "<<h<<endl; v[x][y][h]=1; if(x==n && y==m) { if(!use[h]) ans[++l]=h,use[h]=1; return; } for(int i=0;i<=1;++i) { rx=x+dx[i];ry=y+dy[i]; if(rx<1 || rx>n || ry<1 || ry>m) continue; tmp=1ll*h*a[rx][ry]%(ll)k; dfs(rx,ry,(int)tmp); } } int main() { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%d",&a[i][j]); dfs(1,1,a[1][1]); cout<<l<<endl; sort(ans+1,ans+l+1); for(int i=1;i<=l;++i) cout<<ans[i]<<" "; return 0; }