GYM 101502I. Move Between Numbers

I. Move Between Numbers

time limit per test

memory limit per test

input

output

You are given n magical numbers a*1, *a*2, …, *a**n, such that the length of each of these numbers is 20 digits.

You can move from the i**th number to the j**th number, if the number of common digits between a**i and a**j is exactly 17 digits.

The number of common digits between two numbers x and y is computed is follow:

img.

Where countX**i is the frequency of the i**th digit in the number x, and countY**i is the frequency of the i**th digit in the number y.

You are given two integers s and e, your task is to find the minimum numbers of moves you need to do, in order to finish at number a**e*starting from number *a**s.

Input

The first line contains an integer T (1 ≤ T ≤ 250), where T is the number of test cases.

The first line of each test case contains three integers n, s, and e (1 ≤ n ≤ 250) (1 ≤ s, e ≤ n), where n is the number of magical numbers, s is the index of the number to start from it, and e is the index of the number to finish at it.

Then n lines follow, giving the magical numbers. All numbers consisting of digits, and with length of 20 digits. Leading zeros are allowed.

Output

For each test case, print a single line containing the minimum numbers of moves you need to do, in order to finish at number a**e starting from number a**s. If there is no answer, print -1.

Example

Copy

1
5 1 5
11111191111191111911
11181111111111818111
11811171817171181111
11111116161111611181
11751717818314111118

output

3

Note

In the first test case, you can move from *a*1 to *a*2, from *a*2 to *a*3, and from *a*3 to *a*5. So, the minimum number of moves is 3 moves.

题意

​ 给出n个20位的数,求第s到第e的最少步数。

​ 能走的条件是这样的: 如果两个数相同数字个数的和为17,那么就能互相到达。例如a1与a2公有17个1,那么可以互相到达,a2与a3公有14个1和3个8,它们的总和为17,则它们也可以互相到达。

解题思路

​ 建图,BFS(dijkstra也行)。

代码

#include<bits/stdc++.h>
using namespace std;
#define maxn 300
#define inf 0x3f3f3f3f

int number1[10],number2[10],flag[maxn];
string str[maxn];
vector<int> v[maxn];
int s,e;
struct node
{
    int x,step;
    node() {}
    node(int a,int b)
    {
        x=a;
        step=b;
    }
};
void bfs()
{
    memset(flag,0,sizeof(flag));
    queue<node> q;
    flag[s]=1;
    q.push(node(s,0));
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        flag[now.x]=1;
        if(now.x==e)
        {
            printf("%d\n",now.step);
            return;
        }
        for(int i=0; i<v[now.x].size(); i++)
        {
            node next=now;
            next.x=v[now.x][i];
            if(flag[next.x]) continue;
            next.step=now.step+1;
            q.push(next);
        }
    }
    printf("-1\n");
}
int main()
{
//    freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        cin>>n>>s>>e;
        for(int i=0;i<=n;i++)
            v[i].clear();
        for(int i=1; i<=n; i++)
            cin>>str[i];
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                memset(number1,0,sizeof(number1));
                memset(number2,0,sizeof(number2));
                for(int k=0; k<20; k++)
                {
                    number1[str[i][k]-'0']++;
                    number2[str[j][k]-'0']++;
                }
                int sum=0;
                for(int k=0; k<10; k++)
                    sum+=min(number1[k],number2[k]);
                if(sum==17) v[i].push_back(j);
            }
        }
        bfs();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值