洛谷——P2049 魔术棋子

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷——P2049 魔术棋子相关的知识,希望对你有一定的参考价值。

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

 

以上是关于洛谷——P2049 魔术棋子的主要内容,如果未能解决你的问题,请参考以下文章

洛谷—— P2049 魔术棋子

魔术棋子

魔术棋子

题解魔术棋子

题解魔术棋子

洛谷 P3182 [HAOI2016]放棋子 题解