標籤:code from dex 資料 排列 oca fstream 問題 最大值
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-4using 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('\n'); }}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;}
luogu P1549 棋盤問題(2) 題解