8.1--集训日记--搜索+练习赛

今天一天没怎么看知识点。一直在做题。

上午做了一道比较简单的题,但是做了好久。题目如下:

(题目大意就是给两个四位数,每次变动一位数,多少次可以变到指定数字。期间所有的数都要是素数)

The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit room numbers on their offices. 
— It is a matter of security to change such things every now and then, to keep the enemy in the dark. 
— But look, I have chosen my number 1033 for good reasons. I am the Prime minister, you know! 
— I know, so therefore your new number 8179 is also a prime. You will just have to paste four new digits over the four old ones on your office door. 
— No, it’s not that simple. Suppose that I change the first digit to an 8, then the number will read 8033 which is not a prime! 
— I see, being the prime minister you cannot stand having a non-prime number on your door even for a few seconds. 
— Correct! So I must invent a scheme for going from 1033 to 8179 by a path of prime numbers where only one digit is changed from one prime to the next prime. 

Now, the minister of finance, who had been eavesdropping, intervened. 
— No unnecessary expenditure, please! I happen to know that the price of a digit is one pound. 
— Hmm, in that case I need a computer program to minimize the cost. You don't know some very cheap software gurus, do you? 
— In fact, I do. You see, there is this programming contest going on... Help the prime minister to find the cheapest prime path between any two given four-digit primes! The first digit must be nonzero, of course. Here is a solution in the case above. 

1033 
1733 
3733 
3739 
3779 
8779 
8179
The cost of this solution is 6 pounds. Note that the digit 1 which got pasted over in step 2 can not be reused in the last step – a new 1 must be purchased.

Input
One line with a positive number: the number of test cases (at most 100). Then for each test case, one line with two numbers separated by a blank. Both numbers are four-digit primes (without leading zeros).
Output
One line for each case, either with a number stating the minimal cost or containing the word Impossible.
Sample Input
3
1033 8179
1373 8017
1033 1033

Sample Output
6
7
0

求步数,所以考虑到用BFS。又因为每一步的数都要是素数,所以要进行预处理,即筛素数。由于这个数字范围比较小,都是四位数。但是还是忘了筛素数怎么筛,于是又查了资料。 解题思路既然是BFS,那么就还是用队列去做。 先将取出的四位数字合起来,看看是否和目标数字一样,若一样终止搜索。否则将数字分开,变换一位数,判断是否为素数,若是,则步数增一压入队列。本来是一道比较简单的题,但是因为脑子晕乎,在步数上浪费了很长时间,不应该…… 下面附源代码:


#include <iostream>

#include <queue>

#include <cstring>

#include <algorithm>

#include <stdio.h>

#define MAX 10000

using namespace std;

int start_num, end_num,sum = 0;

bool prime[MAX];

int flag[MAX];

struct Number

{

    int wei[4];

    int step;

}number1,number2,number3;

void Prime() //筛素数

{

    int i,j;

    for(i = 0; i < MAX; i++)

        prime[i] = 1;

    prime[0] = prime[1] = 0;

    for(i = 2; i < MAX; i++)

    {

        if(prime[i] == 1)

        {

            for(j = i+i; j < MAX; j+=i)

            {

                prime[j]=0;

            }

        }

    }

}

void BFS(int a,int b)

{

    queue <Number> q;

    number1.wei[0] = a / 1000;

    number1.wei[1] = (a / 100) % 10;

    number1.wei[2] = (a / 10) % 10;

    number1.wei[3] = a % 10;

    number1.step = 0;

    //cout << number1.wei[0] << endl << number1.wei[1] << endl << number1.wei[2] << endl << number1.wei[3] << endl;

    q.push(number1);

    while (!q.empty())

    {

        number2 = q.front();

        q.pop();

        int i,j,c;

        if (number2.wei[0] * 1000 + number2.wei[1] * 100 + number2.wei[2] * 10 + number2.wei[3] == b)

        {

            cout << number2.step << endl;

            break;

        }

        for (i = 0; i < 4; i++)

        {

            for (j = 0; j <= 9; j++)

            {

                if (i == 0 && j == 0)

                    continue;

                if (number2.wei[i] == j)

                    continue;

                else

                {

                    number3.wei[0] = number2.wei[0];

                    number3.wei[1] = number2.wei[1];

                    number3.wei[2] = number2.wei[2];

                    number3.wei[3] = number2.wei[3];

                    number3.wei[i] = j;

                    c = number3.wei[0] * 1000 + number3.wei[1] * 100 + number3.wei[2] * 10 + number3.wei[3];

                    if (prime[c] == 1 && flag[c] == 0)

                    {

                        flag[c] = 1;

                        number3.step = number2.step + 1;

                        q.push(number3);

                    }

                }

            }

        }

    }

}

int main()

{

    int n;

    Prime();

    cin >> n;

    while (n--)

    {

        cin >> start_num >> end_num;

        sum = 0;

        memset(flag,0,sizeof(flag));

        BFS(start_num,end_num);

    }

    return 0;

}




下午做了一场练习赛,也是这个假期第一场练习赛。结果很不理想。只做了一道水题。很气的是第三道题是一道思维题,我却当成了搜索去做。最后得到了第一组数据的答案,但是很明显的超时……还是拿到题要先考虑有没有别的方法。多考虑一下再动手写程序。因为那一道题耽误了时间,所以导致一道水题没有时间做。

今天还是比较失败的……总结经验。不过在练习赛后的补题过程中,还是学到了很多东西。
附两道没有A 的题:

It's the end of July – the time when a festive evening is held at Jelly Castle! Guests from all over the kingdom gather here to discuss new trends in the world of confectionery. Yet some of the things discussed here are not supposed to be disclosed to the general public: the information can cause discord in the kingdom of Sweetland in case it turns out to reach the wrong hands. So it's a necessity to not let any uninvited guests in.

There are 26 entrances in Jelly Castle, enumerated with uppercase English letters from A to Z. Because of security measures, each guest is known to be assigned an entrance he should enter the castle through. The door of each entrance is opened right before the first guest's arrival and closed right after the arrival of the last guest that should enter the castle through this entrance. No two guests can enter the castle simultaneously.

For an entrance to be protected from possible intrusion, a candy guard should be assigned to it. There are k such guards in the castle, so if there are more than k opened doors, one of them is going to be left unguarded! Notice that a guard can't leave his post until the door he is assigned to is closed.

Slastyona had a suspicion that there could be uninvited guests at the evening. She knows the order in which the invited guests entered the castle, and wants you to help her check whether there was a moment when more than k doors were opened.

Input

Two integers are given in the first string: the number of guests n and the number of guards k (1 ≤ n ≤ 1061 ≤ k ≤ 26).

In the second string, n uppercase English letters s1s2... sn are given, where si is the entrance used by the i-th guest.

Output

Output «YES» if at least one door was unguarded during some time, and «NO» otherwise.

You can output each letter in arbitrary case (upper or lower).

Example
Input
5 1
AABBB
Output
NO
Input
5 1
ABABB
Output
YES

题目大意就是有k个守卫,n个客人,知道客人走的门(A.B......),守卫在守一个门的过程中,在该门的客人未全部进程前不能离开。问能不能守好。

题目比较简单……暴力求解。先求出每个门第一个客人和最后一个客人的位置,然后找需要的守卫是否超出k个。 附源代码:

#include <iostream>

#include <cstring>

#include <algorithm>

#include <string>

#include <queue>

#include <stdio.h>

#include <iomanip>

using namespace std;

int l[27],r[27];

char people[1000005];

int main()

{

    int n,k,i,j;

    while (cin >> n >> k)

    {

        int flag = 0,sum = 0;

        cin >> people;

        for (i = 0; i < 26; i++)

        {

            l[i] = -1;

            r[i] = -1;

        }

        for (i = 0; i < n; i++)

        {

            if (l[people[i] - 65] == -1)

                l[people[i] - 65] = i;

        }

        for (i = n-1; i >= 0; i--)

        {

            if (r[people[i] - 65] == -1)

                r[people[i]-65] = i;

        }

      //  for (i = 0; i < 2; i++)

        //    cout << l[i] << " " << r[i] << endl;

        for (i = 0; i < n; i++)

        {

            if (i == l[people[i]-65])

                sum += 1;

            if (sum > k)

            {

                flag = 1;

                break;

            }

            if (i == r[people[i]-65])

                sum -= 1;

        }

        if (flag == 1)

            cout << "YES" << endl;

        else

            cout << "NO" << endl;

    }

    return 0;

}


还有一个题。就是误解为搜索的题目:

Slastyona and her loyal dog Pushok are playing a meaningless game that is indeed very interesting.

The game consists of multiple rounds. Its rules are very simple: in each round, a natural number k is chosen. Then, the one who says (or barks) it faster than the other wins the round. After that, the winner's score is multiplied by k2, and the loser's score is multiplied by k. In the beginning of the game, both Slastyona and Pushok have scores equal to one.

Unfortunately, Slastyona had lost her notepad where the history of all n games was recorded. She managed to recall the final results for each games, though, but all of her memories of them are vague. Help Slastyona verify their correctness, or, to put it another way, for each given pair of scores determine whether it was possible for a game to finish with such result or not.

Input

In the first string, the number of games n (1 ≤ n ≤ 350000) is given.

Each game is represented by a pair of scores ab (1 ≤ a, b ≤ 109) – the results of Slastyona and Pushok, correspondingly.

Output

For each pair of scores, answer "Yes" if it's possible for a game to finish with given score, and "No" otherwise.

You can output each letter in arbitrary case (upper or lower).

Example
Input
6
2 4
75 45
8 8
16 16
247 994
1000000000 1000000
Output
Yes
Yes
Yes
No
No
Yes

题目大意:给两个数,这两个数是由n组比赛得来的,每组比赛赢方得k^2分,输方得k分,每局得分相乘,k是自然数。 开始理解为搜索,就是建立了一个数组,存放一些数和平方,找看有没有乘积是结果的。结果超时…… 后来看题解,才发现自己好愚蠢……两个结果(a,b)的乘积就是k的三次方,所以只需要找k满足k的三次方为a*b,可以用二分法进行查找,也可以开三次方根。我用的二分法去找的。源代码如下:

#include <iostream>

using namespace std;

int flag = 0;

void solve(long long a,long long b,long long c)

{

    int l = 1,r = 1000000;

    long long mid;

    while (l <= r)

    {

        mid = (l + r ) / 2;

        if (mid * mid * mid == a)

        {

            if (b % mid == 0 && c % mid == 0) //要保证这两个数与得到的结果模为0

            {

                flag = 1;

                return ;

            }

        }

        if (mid * mid * mid < a)

            l = mid + 1;

        else

            r = mid - 1;

    }

}

int main()

{

    int n;

    scanf("%d",&n);

    while (n--)

    {

        long long a,b;

        scanf("%lld%lld",&a,&b);

        flag = 0;

        solve(a * b,a,b);

        if (flag == 1)

            printf("YES\n");

        if (flag == 0)

            printf("NO\n");

    }

    return 0;

}


这个题做好后还WA了,又把cin改成了scanf,就A了……
今天不怎么成功……虽然没看知识点,但是通过做题也学到了不少东西。还是要继续努力。 看数独的题比较有意思……再试试~ 明天要加油~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值