[USACO 6.4.1] The Primes

题目大意

  给一个5*5的矩阵,在每个格子里面填入0~9这10个数字.要求行从左往右读,列从上往下读,两条对角线从上往下读是一个5位素数且不含前导0.

  现在给出了开头的数字和行,列,对角线之和,求符合规定的所有数字矩阵.

题解

  这是一道搜索题.

  但盲目的搜索是会TLE的.因此,我们应当采用合理的剪枝.

  由题目可知,加入行列对角线我们知道了任意4位数,我们可以推出第5位数是什么.

  因此,我们可以采用传说中的手动指定搜索顺序的方法来搜索和回溯.

  具体搜索顺序如下图.

 

  大概就是这样的感觉.

  里面的C是可以直接算出来的.所以我们只需要搜索只有数字那些就行了.

  还有我一开始是枚举对角线素数.

  注意: 先枚举每个数的最后一位会让你减少至少一半的搜索量.因为5位素数的最后一位数肯定不是偶数.

  详情请看代码.代码有点恶心.我用了宏定义,因为这样看起来会更加恶心.

代码

/*
TASK:prime3
LANG:C++
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#define REP(i,st,ed) for ((i) = (st); (i) < (ed); ++(i))

using namespace std;

struct Ans
{
    int matrix[5][5];
    
    Ans operator = (Ans &rhs)
    {
        memcpy(matrix, rhs.matrix, sizeof(rhs.matrix));
        return *this;
    }
    
    bool operator < (const Ans &rhs) const
    {
        for (int i = 0; i < 5; ++i)
            for (int j = 0; j < 5; ++j)
                if (matrix[i][j] < rhs.matrix[i][j]) return true;
                else if (matrix[i][j] > rhs.matrix[i][j]) return false;
        return false;
    }
    
}ans[1000], tmp;
int anslen;

const int MAXP = 100000;
int p[10000], np, sumallr[5], sumallc[5], sumalld, sum;
bool v[MAXP * 10];

bool check(int x)
{
    int s = 0;
    while (x) s += x % 10, x /= 10;
    return s == sum;
}

void filtrate()
{
    memset(v, true, sizeof(v));
    for (int i = 2; i < MAXP; ++i)
        for (int j = 2; i * j < MAXP; ++j)
            v[i * j] = false;
    np = 0;
    for (int i = 10000; i < MAXP; ++i)
        if (v[i] && check(i)) p[np++] = i;
}

bool judge(int x, int y)
{
    if (sumallr[x] + tmp.matrix[x][y] > sum) return false;
    if (sumallc[y] + tmp.matrix[x][y] > sum) return false;
    if (4 - x == y && sumalld + tmp.matrix[x][y] > sum) return false;
    return true;
}

void adds(int x, int y, int d)
{
    sumallr[x] += tmp.matrix[x][y] * d;
    sumallc[y] += tmp.matrix[x][y] * d;
    if (4 - x == y) sumalld += tmp.matrix[x][y] * d;
}

int trans(int d, int m)
{
    if (m == 1) return tmp.matrix[d][0] * 10000 
                        + tmp.matrix[d][1] * 1000
                        + tmp.matrix[d][2] * 100
                        + tmp.matrix[d][3] * 10
                        + tmp.matrix[d][4];
    else if (m == 2) return tmp.matrix[0][d] * 10000
                            + tmp.matrix[1][d] * 1000
                            + tmp.matrix[2][d] * 100
                            + tmp.matrix[3][d] * 10
                            + tmp.matrix[4][d];
    else if (m == 3) return tmp.matrix[4][0] * 10000
                            + tmp.matrix[3][1] * 1000
                            + tmp.matrix[2][2] * 100
                            + tmp.matrix[1][3] * 10
                            + tmp.matrix[0][4];
}

bool condit(int x)
{
    return x >= 0 && x <= 9;
}

int main()
{
    freopen("prime3.in", "r", stdin);
    freopen("prime3.out", "w", stdout);
    scanf("%d%d", &sum, &tmp.matrix[0][0]);
    filtrate();
    memset(sumallr, 0, sizeof(sumallr));
    memset(sumallc, 0, sizeof(sumallc));
    sumalld = 0;
    anslen = 0;
    for (int i = 0; i < np; ++i)
    {
        if (p[i] * 10 / MAXP != tmp.matrix[0][0]) continue;
        int k = p[i];
        for (int j = 4; j >= 0; --j)
        {
            tmp.matrix[j][j] = k % 10;
            sumallr[j] = sumallc[j] = k % 10;
            k /= 10;
        }
        sumalld = p[i] % 1000 / 100;
        REP(tmp.matrix[0][4], 1, 10)
        {
            if (tmp.matrix[0][4] % 2 == 0 || tmp.matrix[0][4] == 5) continue;
            if (!judge(0, 4)) break;
            adds(0, 4, 1);
            REP(tmp.matrix[1][3], 0, 10)
            {
                if (!judge(1, 3)) break;
                adds(1, 3, 1);
                REP(tmp.matrix[4][0], 1, 10)
                {
                    if (tmp.matrix[4][0] % 2 == 0 || tmp.matrix[4][0] == 5) continue;
                    if (!judge(4, 0)) break;
                    tmp.matrix[3][1] = sum - sumalld - tmp.matrix[4][0];
                    if (!condit(tmp.matrix[3][1]) || !judge(3, 1)) continue;
                    if (!v[trans(0, 3)]) continue;
                    adds(3, 1, 1);
                    adds(4, 0, 1);
                    REP(tmp.matrix[1][4], 1, 10)
                    {
                        if (tmp.matrix[1][4] % 2 == 0 || tmp.matrix[1][4] == 5) continue;
                        if (!judge(1, 4)) break;
                        adds(1, 4, 1);
                        REP(tmp.matrix[2][4], 1, 10)
                        {
                            if (tmp.matrix[2][4] % 2 == 0 || tmp.matrix[2][4] == 5) continue;
                            if (!judge(2, 4)) break;
                            tmp.matrix[3][4] = sum - sumallc[4] - tmp.matrix[2][4];
                            if (!condit(tmp.matrix[3][4]) || !judge(3, 4)) continue;
                            if (!v[trans(4, 2)]) continue;
                            adds(3, 4, 1);
                            adds(2, 4, 1);
                            REP(tmp.matrix[4][3], 1, 10)
                            {
                                if (tmp.matrix[4][3] % 2 == 0 || tmp.matrix[4][3] == 5) continue;
                                if (!judge(4, 3)) break;
                                adds(4, 3, 1);
                                REP(tmp.matrix[0][3], 1, 10)
                                {
                                    if (!judge(0, 3)) break;
                                    tmp.matrix[2][3] = sum - sumallc[3] - tmp.matrix[0][3];
                                    if (!condit(tmp.matrix[2][3]) || !judge(2, 3)) continue;
                                    if (!v[trans(3, 2)]) continue;
                                    adds(0, 3, 1);
                                    adds(2, 3, 1);
                                    REP(tmp.matrix[4][2], 1, 10)
                                    {
                                        if (tmp.matrix[4][2] % 2 == 0 || tmp.matrix[4][2] == 5) continue;
                                        if (!judge(4, 2)) break;
                                        adds(4, 2, 1);
                                        REP(tmp.matrix[3][2], 0, 10)
                                        {
                                            if (!judge(3, 2)) break;
                                            adds(3, 2, 1);
                                            REP(tmp.matrix[0][2], 1, 10)
                                            {
                                                if (!judge(0, 2)) break;
                                                tmp.matrix[1][2] = sum - sumallc[2] - tmp.matrix[0][2];
                                                if (!condit(tmp.matrix[1][2]) || !judge(1, 2) || !v[trans(2, 2)]) continue;
                                                tmp.matrix[0][1] = sum - sumallr[0] - tmp.matrix[0][2];
                                                if (tmp.matrix[0][1] == 0) continue;
                                                if (!condit(tmp.matrix[0][1]) || !judge(0, 1) || !v[trans(0, 1)]) continue;
                                                tmp.matrix[4][1] = sum - sumallr[4];
                                                if (!condit(tmp.matrix[4][1]) || !judge(4, 1) || !v[trans(4, 1)]) continue;
                                                tmp.matrix[2][1] = sum - sumallc[1] - tmp.matrix[0][1] - tmp.matrix[4][1];
                                                if (!condit(tmp.matrix[2][1]) || !judge(2, 1) || !v[trans(1, 2)]) continue;
                                                tmp.matrix[1][0] = sum - sumallr[1] - tmp.matrix[1][2];
                                                if (tmp.matrix[1][0] == 0) continue;
                                                if (!condit(tmp.matrix[1][0]) || !judge(1, 0) || !v[trans(1, 1)]) continue;
                                                tmp.matrix[2][0] = sum - sumallr[2] - tmp.matrix[2][1];
                                                if (tmp.matrix[2][0] == 0) continue;
                                                if (!condit(tmp.matrix[2][0]) || !judge(2, 0) || !v[trans(2, 1)]) continue;
                                                if (sumallc[0] + tmp.matrix[1][0] + tmp.matrix[2][0] != sumallr[3]) continue;
                                                tmp.matrix[3][0] = sum - sumallr[3];
                                                if (tmp.matrix[3][0] == 0) continue;
                                                if (!condit(tmp.matrix[3][0]) || !v[trans(0, 2)] || !v[trans(3, 1)]) continue;
                                                ans[anslen++] = tmp;
                                            }
                                            adds(3, 2, -1);
                                        }
                                        adds(4, 2, -1);
                                    }
                                    adds(0, 3, -1);
                                    adds(2, 3, -1);
                                }
                                adds(4, 3, -1);
                            }
                            adds(3, 4, -1);
                            adds(2, 4, -1);
                        }
                        adds(1, 4, -1);
                    }
                    adds(4, 0, -1);
                    adds(3, 1, -1);
                }
                adds(1, 3, -1);
            }
            adds(0, 4, -1);
        }
    }
    sort(ans, ans + anslen);
    for (int k = 0; k < anslen; ++k)
    {
        if (k != 0) printf("\n");
        for (int i = 0; i < 5; ++i)
        {
            for (int j = 0; j < 5; ++j)
                printf("%d", ans[k].matrix[i][j]);
            printf("\n");
        }
    }
    return 0;
}

 

posted @ 2016-08-04 12:29  albertxwz  阅读(429)  评论(0编辑  收藏  举报