P2049 魔术棋子
题目描述
在一个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:
Magic.in 2 3 5 3 4 4 5 6 6
输出样例#1:
3 0 2 3
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; priority_queue<int,vector<int>,greater<int> >q; int n,m,mod,ans,a[110][110]; bool vist[110][110],vis[110]; int xx[2]={0,1},yy[2]={1,0}; int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1; ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } void dfs(int x,int y,int s) { if(x==n&&y==m) { if(vis[s]) return ; vis[s]=true,ans++; q.push(s);return ; } for(int i=0;i<2;i++) { int fx=x+xx[i],fy=y+yy[i]; if(fx>0&&fy>0&&fx<=n&&fy<=m&&!vist[fx][fy]) { vist[fx][fy]=true; dfs(fx,fy,(s*a[fx][fy])%mod); vist[fx][fy]=false; } } } int main() { n=read(),m=read(),mod=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(),a[i][j]%=mod; dfs(1,1,a[1][1]); printf("%d\n",ans); while(!q.empty()) { n=q.top(); q.pop(); printf("%d ",n); } return 0; }
20分TLE的dfs
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,m,mod,ans,a[110][110]; int xx[2]={0,1},yy[2]={1,0}; bool vist[110][110][110],vis[110]; priority_queue<int,vector<int>,greater<int> >q; int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1; ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } void dfs(int x,int y,int s) { if(x==n&&y==m) { if(vis[s]) return ; vis[s]=true,ans++; q.push(s);return ; } if(vist[x][y][s]) return ; vist[x][y][s]=true; for(int i=0;i<2;i++) { int fx=x+xx[i],fy=y+yy[i]; if(fx>0&&fy>0&&fx<=n&&fy<=m) dfs(fx,fy,(s*a[fx][fy])%mod); } // vist[x][y][s]=false; } int main() { n=read(),m=read(),mod=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(),a[i][j]%=mod; dfs(1,1,a[1][1]); printf("%d\n",ans); while(!q.empty()) { n=q.top(); q.pop(); printf("%d ",n); } return 0; }
AC的记忆化搜索
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; bool dp[110][110][110]; int n,m,k,ans,a[110][110]; int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1; ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} return x*f; } int main() { n=read(),m=read(),k=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(),a[i][j]%=k; dp[1][1][a[1][1]]=true; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int s=0;s<k;s++) if(!dp[i][j][s*a[i][j]%k]) dp[i][j][s*a[i][j]%k]=dp[i][j-1][s]||dp[i-1][j][s]; for(int i=0;i<k;i++) if(dp[n][m][i]) ans++; printf("%d\n",ans); for(int i=0;i<k;i++) if(dp[n][m][i]) printf("%d ",i); return 0; }
dp
时间: 2024-10-13 00:29:40