noip模拟赛 PA

分析:很显然这是一道搜索题,可能是由于我的搜索打的太不美观了,这道题又WA又T......如果对每一个询问都做一次bfs是肯定会T的,注意到前70%的数据范围,N的值都相等,我们可以把给定N的所有情况给算出来,然后O(1)查询.从终点状态往起点状态BFS就可以了.

当最终状态很少,起始状态很多的时候,可以考虑倒着做.

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int T, jian[10], stu, shu[10], cnt, top[10], d[10000000], cur[10], vis[10000000];
int n, a[10], b[10];
queue <int> q;

bool cmp(int x, int y)
{
    return a[x] < a[y];
}

void bfs()
{
    while (!q.empty())
    {
        int zhuangtai = q.front();
        q.pop();
        memset(top, 0, sizeof(top));
        memset(shu, 0, sizeof(shu));
        cnt = 0;
        int tt = zhuangtai;
        while (tt)
        {
            shu[++cnt] = tt % 10;
            tt /= 10;
        }
        reverse(shu + 1, shu + 1 + cnt);
        for (int i = cnt; i >= 1; i--)
            top[shu[i]] = i;
        for (int i = 1; i <= cnt; i++)
            if (i == top[shu[i]])
            {
            int temp = shu[i];
            if (temp != 1 && (i < top[temp - 1] || !top[temp - 1]))
            {
                int newstu = zhuangtai - jian[cnt - i];
                if (!vis[newstu])
                {
                    q.push(newstu);
                    vis[newstu] = 1;
                    d[newstu] = d[zhuangtai] + 1;
                }
            }

            if (temp != cnt && (i < top[temp + 1] || !top[temp + 1]))
            {
                int newstu = zhuangtai + jian[cnt - i];
                if (!vis[newstu])
                {
                    q.push(newstu);
                    vis[newstu] = 1;
                    d[newstu] = d[zhuangtai] + 1;
                }
            }
            }
    }
}

int main()
{
    scanf("%d", &T);
    jian[0] = 1;
    stu = 0;
    for (int i = 1; i <= 7; i++)
    {
        jian[i] = jian[i - 1] * 10;
        stu = stu * 10 + i;
        q.push(stu);
        vis[stu] = 1;
    }
    bfs();
    //printf("flag\n");
    while (T--)
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            b[i] = i;
        }
        sort(b + 1, b + 1 + n, cmp); 
        int stu = 0;
        for (int i = 1; i <= n; i++)
            stu = stu * 10 + b[i];
        if (!vis[stu])
            printf("-1\n");
        else
            printf("%d\n", d[stu]);
    }

    return 0;
}

 

posted @ 2017-10-23 13:47  zbtrs  阅读(171)  评论(0编辑  收藏  举报