UVALive7672

这道题目如果每一次都广搜一次会超时。先打表就可以了。

思路是定义数组step[maxn][5][5];数组元素step[n][i][j]表示在i步增加操作和j步双倍操作后对于"12345"转换到数字n的最小步数,打表形成可能的所有数字变换的情况。经验:利用打表的思想可以大大减少时间复杂度。

#include
#include
#include
#include
using namespace std;
const int maxn=100100;
const int inf=0x3f3f3f3f;
int step[maxn][5][5];
int str;
void bfs(int a[],int inc,int dou,int num)//num是开始时的步数
{
    int base=10000;
    int p=0;
    for(int i=0; i<=4; i++)
    {
        p+=a[i]*base;
        base/=10;
    }
    if(step[p][inc][dou]<=num)
        return;
//step数组的第一维是数字,数组储存的是最小次数
    step[p][inc][dou]=num;
    int b[5];
    if(inc<3)
        for(int i=0; i<=4; i++)
        {
            for(int j=0; j<=4; j++)
                b[j]=a[j];
            b[i]=(b[i]+1)%10;
            bfs(b,inc+1,dou,num+1);
        }
    if(dou<2)
        for(int i=0; i<=4; i++)
        {
            for(int j=0; j<=4; j++)
                b[j]=a[j];
            b[i]=(b[i]<<1)%10;
            bfs(b,inc,dou+1,num+1);
        }
    for(int i=0; i<4; i++)
    {
        for(int j=0; j<=4; j++)
            b[j]=a[j];
        swap(b[i+1],b[i]);
        bfs(b,inc,dou,num+1);
    }
}
int main()
{
    int a[5]= {1,2,3,4,5};
    memset(step,inf,sizeof(step));
    bfs(a,0,0,0);
    while(~scanf("%d",&str))
    {
        int ans=inf;
        for(int i=0; i<=2; i++)
            for(int j=0; j<=3; j++)
                ans=min(ans,step[str][j][i]);
        if(ans==inf)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

 

你可能感兴趣的:(动态规划,BFS和DFS)