【USACO 4.3.2】質數方陣


毒瘤題解

loj題目傳送門

題目大意:有一個5*5的方陣,給出左上角的一個數以及每一行、每一列、每一斜行的數字和,求所有可能的填數方案並且按照方陣從上往下、從左往右組成的25位數從小到大排序。

(要保證每一行、每一列、每一斜行的五個數從左往右組成的五位數是一個五位質數,有前導0的不算)

tag:深搜


下面讓我們來捋一捋:

1.這是一個填表游戲(貌似廢話)

2.每一行的五個數,其實要去枚舉的最多的只有三個數而已,剩余的一個可以用總和推出來

3.填一個數時,可能要判斷多次,因為填下一個數可能會導致好幾個行或者列被填滿,需要判斷;所以使用某些填表順序的時候可能比較繁瑣,要盡量避開這些詭異的格點。

(Tips:這些東西真的真的一定要避開,要不然填表的時候填着填着自己都會亂掉或是查錯的時候難以查出,曾經修改兩次填表順序,繁瑣的要命)

4.其實要解決的就是一個填表順序的問題

5.填表的起點非常顯然:左斜行,第一行或第一列。

6.填表過程中,若有一段已經被填上了4個數,則可以直接推出來剩下的一個

7.若推剩下這個數的時候,扣掉之后這個數>9或<0,則方案不可行


以下圖片可能有點糊,S表示已知或者推出來的,X表示枚舉出來的

所以下面就要來解決這個問題:

那我們就先從第一斜行填起吧!(所有名字里帶着f1的函數都是)

然后就是第一列(帶f2的)

然后第二行(帶f3的)

接着搞定右斜行(帶f4的)

然后搞定第三行(很繁瑣是不是)(帶f5的)

注意,此時可以把第五列推出來

然后可以把第四行推出來

下面搞定第二列(帶f6的)

然后再搞定第三列(帶f7的)

順便把第一行搞定掉

最后搞定第五行、第四列;

注意!!!這個地方要判斷兩邊,必須要第五行、第四列推出來的那個數一樣以及行、列都滿足其他條件(質數等)才能視為這個方案是OK的,top++;

於是就OK啦!

169行code:

#include<bits/stdc++.h>
using namespace std;
bool prime[100001];
void prim(){
    for(register int i=2;i<=sqrt(100000);i++){
        if(!prime[i]){
            for(register int j=i+i;j<=100000;j+=i)prime[j]=1;
        }
    }
}
struct data{
    int a[6][6];
    bool operator <(const data &d)const{
        for(register int i=1;i<=5;i++){
            for(register int j=1;j<=5;j++){
                if(a[i][j]<d.a[i][j])return 1;
                else if(a[i][j]>d.a[i][j])return 0;
            }
        }
        return 0;
    }
    bool operator =(const data &d){
        for(register int i=1;i<=5;i++){
            for(register int j=1;j<=5;j++){
                a[i][j]=d.a[i][j];
            }
        }
    }
}bas[10001];
int sum,s,top=0;
bool check(int a1,int a2,int a3,int a4,int a5){
	int num=a1*10000+a2*1000+a3*100+a4*10+a5;
    if(num<10000)return 0;
    return !prime[num];
}
void f7(){
    for(register int i=0;i<=9;i++){
		bas[top].a[1][3]=i;
		int num=sum-bas[top].a[1][1]-bas[top].a[1][2]-bas[top].a[1][3]-bas[top].a[1][5];
		if(num>9||num<0)continue;bas[top].a[1][4]=num;
		if(!check(bas[top].a[1][1],bas[top].a[1][2],bas[top].a[1][3],bas[top].a[1][4],bas[top].a[1][5]))continue;
		
		num=sum-bas[top].a[1][3]-bas[top].a[2][3]-bas[top].a[3][3]-bas[top].a[4][3];
		if(num>9||num<0)continue;bas[top].a[5][3]=num;
		if(!check(bas[top].a[1][3],bas[top].a[2][3],bas[top].a[3][3],bas[top].a[4][3],bas[top].a[5][3]))continue;
		
		num=sum-bas[top].a[5][1]-bas[top].a[5][2]-bas[top].a[5][3]-bas[top].a[5][5];
		int num2=sum-bas[top].a[1][4]-bas[top].a[2][4]-bas[top].a[3][4]-bas[top].a[4][4];
		if(num>9||num<0||num2!=num)continue;
		bas[top].a[5][4]=num;
		if(!check(bas[top].a[5][1],bas[top].a[5][2],bas[top].a[5][3],bas[top].a[5][4],bas[top].a[5][5])||!check(bas[top].a[1][4],bas[top].a[2][4],bas[top].a[3][4],bas[top].a[4][4],bas[top].a[5][4]))continue;
		top++;bas[top]=bas[top-1];
	}
}
void f6(){
    for(register int i=0;i<=9;i++){
		bas[top].a[1][2]=i;
		int num=sum-bas[top].a[1][2]-bas[top].a[2][2]-bas[top].a[3][2]-bas[top].a[4][2];
		if(num>9||num<0)continue;bas[top].a[5][2]=num;
		if(check(bas[top].a[1][2],bas[top].a[2][2],bas[top].a[3][2],bas[top].a[4][2],bas[top].a[5][2]))f7();
    }
}
void f5(){
    for(register int i=0;i<=9;i++){
		bas[top].a[3][5]=i;
		int num=bas[top].a[4][5]=sum-bas[top].a[1][5]-bas[top].a[2][5]-bas[top].a[3][5]-bas[top].a[5][5];
		if(num>9||num<0)continue;
		if(!check(bas[top].a[1][5],bas[top].a[2][5],bas[top].a[3][5],bas[top].a[4][5],bas[top].a[5][5]))continue;
		
		num=bas[top].a[4][3]=sum-bas[top].a[4][1]-bas[top].a[4][2]-bas[top].a[4][4]-bas[top].a[4][5];
		if(num>9||num<0)continue;
		if(!check(bas[top].a[4][1],bas[top].a[4][2],bas[top].a[4][3],bas[top].a[4][4],bas[top].a[4][5]))continue;
		
		num=sum-bas[top].a[3][1]-bas[top].a[3][3]-bas[top].a[3][4]-bas[top].a[3][5];
		if(num>9||num<0)continue;bas[top].a[3][2]=num;
		if(check(bas[top].a[3][1],bas[top].a[3][2],bas[top].a[3][3],bas[top].a[3][4],bas[top].a[3][5]))f6();
    }
}
void f51(){
	for(register int i=0;i<=9;i++){
		bas[top].a[3][4]=i;
		f5();
	}
}
void f4(){
    for(int i=0;i<=9;i++){
        bas[top].a[1][5]=i;
        int num=sum-bas[top].a[5][1]-bas[top].a[1][5]-bas[top].a[3][3]-bas[top].a[2][4];
        if(num>9||num<0)continue ;bas[top].a[4][2]=num;
        if(check(bas[top].a[5][1],num,bas[top].a[3][3],bas[top].a[2][4],bas[top].a[1][5]))f51();
    }
}
void f3(){
    for(register int i=0;i<=9;i++){
        bas[top].a[2][5]=i;
        int num=sum-bas[top].a[2][1]-bas[top].a[2][2]-bas[top].a[2][4]-bas[top].a[2][5];
        if(num>9||num<0)continue ;bas[top].a[2][3]=num;
        if(check(bas[top].a[2][1],bas[top].a[2][2],num,bas[top].a[2][4],bas[top].a[2][5]))f4();
    }
}
void f31(){
    for(int i=0;i<=9;i++){
        bas[top].a[2][4]=i;
        f3();
    }
}
void f2(){
    for(register int i=0;i<=9;i++){
        bas[top].a[5][1]=i;
        int num=sum-bas[top].a[1][1]-bas[top].a[3][1]-bas[top].a[4][1]-bas[top].a[5][1];
        if(num>9||num<0)continue ;
        bas[top].a[2][1]=num;
        if(check(bas[top].a[1][1],num,bas[top].a[3][1],bas[top].a[4][1],bas[top].a[5][1]))f31();
    }
}
void f22(){
    for(int i=0;i<=9;i++){
        bas[top].a[4][1]=i;
        f2();
    }
}
void f21(){
    for(int i=0;i<=9;i++){
        bas[top].a[3][1]=i;
        f22();
    }
}
void f1(){
    
    for(register int i=0;i<=9;i++){
        bas[top].a[5][5]=i;
        int num=sum-bas[top].a[1][1]-bas[top].a[3][3]-bas[top].a[4][4]-bas[top].a[5][5];
        if(num>9||num<0)continue ;
        bas[top].a[2][2]=num;
        if(check(bas[top].a[1][1],num,bas[top].a[3][3],bas[top].a[4][4],bas[top].a[5][5]))f21();
    }
}
void f12(){
    for(int i=0;i<=9;i++){
        bas[top].a[4][4]=i;
        f1();
    }
}
void f11(){
    for(int i=0;i<=9;i++){
        bas[top].a[3][3]=i;
        f12();
    }
}
void does(){
    bas[top].a[1][1]=s;
    f11();
    sort(bas,bas+top);
    for(int i=0;i<top;i++){
		for(int j=1;j<=5;j++){
			for(int k=1;k<=5;k++){
				cout<<bas[i].a[j][k];
			}
			cout<<endl;
		}
		cout<<endl;
    }
}
int main(){
    prim();
    cin>>sum>>s;
    does();
    return 0;
}

這題我調了6個半小時,可能是我太弱了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM