zoukankan      html  css  js  c++  java
  • luogu P1549 棋盘问题(2) 题解

    luogu P1549 棋盘问题(2) 题解

    题目描述

    (N * N)的棋盘上((1≤N≤10)),填入(1,2,…,N^2)(N^2)个数,使得任意两个相邻的数之和为素数。

    例如:当(N=2)时,有:

    其相邻数的和为素数的有:

    (1+2,1+4,4+3,2+3)

    (N=4)时,一种可以填写的方案如下:

    在这里我们约定:左上角的格子里必须填数字(1)

    输入输出格式

    输入格式:

    一个数(N)

    输出格式:

    如有多种解,则输出第一行、第一列之和为最小的排列方案;若无解,则输出“NO”。

    输入输出样例

    输入样例#1:

    1

    输出样例#1:

    NO

    输入样例#2:

    2

    输出样例#2:

    1 2
    4 3

    思路

    看这数据这么小((1≤N≤10)),所以可以dfs。
    但是dfs直接跑一下一定是不行的。所以,可以发现题面的要求:输出第一行、第一列之和为最小的排列方案。
    那么怎样使它最小呢?
    很简单,只要在第一行、第一列dfs的枚举时,(i)枚举顺序为(1~n^2),而不是第一行、第一列的其他数字则要取最大值,即枚举顺序为(n^2~1)(down to)。
    然后就是dfs了啊。。。
    素数怎么判断呢??
    预处理一下200之内的素数,然后用桶判断一下就好了呀。
    ps:素数判断可以直接只判断dfs的左、上之和(已经搜索了的数)与之和是不是素数就好了。
    下附代码:

    #include<algorithm>
    #include<bitset>
    #include<complex>
    #include<deque>
    #include<exception>
    #include<fstream>
    #include<functional>
    #include<iomanip>
    #include<ios>
    #include<iosfwd>
    #include<iostream>
    #include<istream>
    #include<iterator>
    #include<limits>
    #include<list>
    #include<locale>
    #include<map>
    #include<memory>
    #include<new>
    #include<numeric>
    #include<ostream>
    #include<queue>
    #include<set>
    #include<sstream>
    #include<stack>
    #include<stdexcept>
    #include<streambuf>
    #include<string>
    #include<typeinfo>
    #include<utility>
    #include<valarray>
    #include<vector>
    #include<cstring>
    #include<cmath>
    #define ll long long 
    #define eps 1e-4
    using namespace std;
    //priority_queue<int,vector<int>,greater<int> > q1;
    //priority_queue<int> q2;
    //set<int> s;
    //list<int> l;
    //map<int> mp;
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();}
    	while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
    	return ret*f;
    }
    inline void write(int zx){
    	if(zx<0){zx=-zx;putchar('-');}
    	if(zx<10) putchar(zx+'0');
    	else{
    		write(zx/10);
    		putchar(zx%10+'0');
    	}
    }
    int n;
    int f[15][15],ans;
    int prime[500];
    bool used[500];
    bool check(int zx){
    	for(int i=2;i<=sqrt(zx);i++)
    		if(zx%i==0) return 0;
    	return 1;
    }
    void print(){
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++){
    			write(f[i][j]);putchar(' ');
    		}
    		putchar('
    ');
    	}
    }
    void dfs(int x,int y){
    	if(x==n&&y==n+1){
    		ans=1;
    		print();
    		exit(0);
    	}
    	if(f[x][y]!=0) return ;
    	if(y==n+1){
    		dfs(x+1,1);
    		return ;
    	}
    	int from=-1;
    	if(x==1||y==1){
    		for(int i=2;i<=n*n;i++){
    			if(used[i]==1) continue ;
    			if(x==1&&prime[f[x][y-1]+i]==0) continue ;
    			if(y==1&&prime[f[x-1][y]+i]==0) continue ;
    			f[x][y]=i;used[i]=1;
    			dfs(x,y+1);
    			f[x][y]=0;used[i]=0;
    		}
    	}else{
    		for(int i=n*n;i>=2;i--){
    			if(used[i]==1) continue ;
    			if(prime[f[x][y-1]+i]==0) continue ;
    			if(prime[f[x-1][y]+i]==0) continue ;
    			f[x][y]=i;used[i]=1;
    			dfs(x,y+1);
    			f[x][y]=0;used[i]=0;
    		}
    	}
    }
    int main(){
    	n=read();
    	if(n==1){
    		puts("NO");
    		return 0;
    	}
    	for(int i=2;i<=500;i++)
    		if(check(i)==1) prime[i]=1;
    	f[1][1]=1;used[1]=1;
    	dfs(1,2);
    	puts("NO");
    	return 0;
    }
    
  • 相关阅读:
    tee命令
    linux优化之SElinux关闭
    (1)使用bash脚本实现批量添加用户
    Django admin管理工具的使用、定制及源码解析
    Mysql常见命令
    树梅派
    19道Python循环遍历,while,for语句测试题,网上看到的题目,自己不看答案全部做了一次,总共3个小时左右
    9*9的矩形,中间有个星号,按不同方向键,星星对应移动
    app在admin中显示成我们想要的中文名
    九九乘法表
  • 原文地址:https://www.cnblogs.com/yzx1798106406/p/9792534.html
Copyright © 2011-2022 走看看