您的位置:首页 > 其它

暑假集训日记--8.5--搜索

2017-08-05 22:31 316 查看
今天一天基本上都在找错误的过程中……

首先附昨天调试没通过的题:

Problem Description

You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:
FILL(i)        fill the pot i (1 ≤ ≤ 2) from the tap;
DROP(i)      empty the pot i to the drain;
POUR(i,j)    pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its
contents have been moved to the pot j).

Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.

 

Input

<p>On the first and only line are the numbers <b>A</b>, <b>B</b>, and <b>C</b>. These are all integers in the range from 1 to 100 and <b>C</b>≤max(<b>A</b>,<b>B</b>).</p>

 

Output

<p>The first line of the output must contain the length of the sequence of operations <b>K</b>. The following <b>K</b> lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t
be achieved, the first and only line of the file must contain the word ‘<b>impossible</b>’.</p>

 

Sample Input

3 5 4

 

Sample Output

6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)

 
这是一个倒水的问题。就是有6种操作。

/*

 1:Fill(1);给1倒满水

 2:Fill(2);给2倒满水

 3:Drop(1);倒空1

 4:Drop(2);倒空2

 5:Pour(1,2);1倒到2

 6:Pour(2,1);2倒到1

*/

这个题的主要思路就是用广搜,执行操作。但这个题的难点是记录路径……

啊……又是记录路径的问题。

刚开始想了好久都没弄懂怎么记录路径,看了看题解,是用指针记录的。研究了一晚上,结果RE。。。不过那种方法能懂了,就不再细说了。

下面用到的方法是在该次操作的结构体对象内记录上一次的操作。

然后最后输出即可。

这个题的广搜不需要用到队列。

之前还有一个类似的倒可乐的例题。

#include <iostream>

#include <cstring>

#include <string>

#include <algorithm>

#include <stdio.h>

#include <queue>

#include <stack>

using namespace std;

struct Tap

{

    int nowa;

    int nowb;

    int oper;

    int pre;

}tap[10000001];

int t,tail;

bool flag;

bool visit[1100][1100] ;

int shit[10000];

void Print()

{

    int step = 0;

    while (t != 0)

    {

        shit[step] = tap[t].oper;

        step++;

        t = tap[t].pre;

    }

    cout << step << endl;

    for (int i = step - 1; i >= 0; i--)

    {

        int q = shit[i] ;

        if (q == 1)

            cout << "FILL(1)" << endl;

        else if (q == 2)

            cout << "FILL(2)" << endl;

        else if (q == 3)

            cout << "DROP(1)" << endl;

        else if (q == 4)

            cout << "DROP(2)" << endl;

        else if (q == 5)

            cout << "POUR(1,2)" << endl;

        else if (q == 6)

            cout << "POUR(2,1)" << endl;

    }

    return ;

}

void BFS(int a,int b,int c)

{

    tap[0].nowa = 0;

    tap[0].nowb = 0;

    tap[0].oper = 0;

    visit[tap[0].nowa][tap[0].nowb] = 1;

    t = 0;

    tail = 1;

    int p1,p2;

    while (t != tail)

    {

        if (tap[t].nowa == c || tap[t].nowb == c)

        {

            Print();

            flag = 1;

            break;

        }

        for (int i = 1; i <= 6; i++)

        {

            if (i == 1)

            {

                p1 = a;

                p2 = tap[t].nowb;

                if (!visit[p1][p2])

                {

                    visit[p1][p2] = 1;

                    tap[tail].nowa = p1;

                    tap[tail].nowb = p2;

                    tap[tail].oper = i;

                    tap[tail++].pre = t;

                }

            }

            else if (i == 2)

            {

                p1 = tap[t].nowa;

                p2 = b;

                if (!visit[p1][p2])

                {

                    visit[p1][p2] = 1;

                    tap[tail].nowa = p1;

                    tap[tail].nowb = p2;

                    tap[tail].oper = i;

                    tap[tail++].pre = t;

                }

            }

            else if (i == 3 )

            {

                p1 = 0;

                p2 = tap[t].nowb;

                if (!visit[p1][p2])

                {

                    visit[p1][p2] = 1;

                    tap[tail].nowa = p1;

                    tap[tail].nowb = p2;

                    tap[tail].oper = i;

                    tap[tail++].pre = t;

                }

            }

            else if (i == 4)

            {

                p1 = tap[t].nowa;

                p2 = 0;

                if (!visit[p1][p2])

                {

                    visit[p1][p2] = 1;

                    tap[tail].nowa = p1;

                    tap[tail].nowb = p2;

                    tap[tail].oper = i;

                    tap[tail++].pre = t;

                }

            }

            else if (i == 5)

            {

                p1 = tap[t].nowa - min(b - tap[t].nowb,tap[t].nowa);

                p2 = tap[t].nowb + min(b - tap[t].nowb,tap[t].nowa);

                if (!visit[p1][p2])

                {

                    visit[p1][p2] = 1;

                    tap[tail].nowa = p1;

                    tap[tail].nowb = p2;

                    tap[tail].oper = i;

                    tap[tail++].pre = t;

                }

            }

            else if (i == 6)

            {

                p1 = tap[t].nowa + min(a - tap[t].nowa,tap[t].nowb);

                p2 = tap[t].nowb - min(a - tap[t].nowa,tap[t].nowb);

                if (!visit[p1][p2])

                {

                    visit[p1][p2] = 1;

                    tap[tail].nowa = p1;

                    tap[tail].nowb = p2;

                    tap[tail].oper = i;

                    tap[tail++].pre = t;

                }

            }

        }

        t++;

    }

    return ;

}

int main()

{

    int a,b,c;

    while(cin >> a >> b >> c)

    {

    memset(visit,0,sizeof(visit));

    flag = false;

    BFS(a,b,c);

    if (flag == 0)

        cout << "impossible" << endl;

    }

    return 0;

}

这个题的记录路径可是折腾了我好长时间。。。。对于我的帮助也比较大。。以后又多了一种记录路径的方式。

之前看C++ primer 的前面,着重看了看指针。这次用指针记录路径的方式,是我没有想到的。虽然RE,但指针依旧是一个非常重要的也是不太容易搞懂的东西。。。还需要继续研究。。

今天还A了两道题。。

比较郁闷的是今晚又找了一晚上错,最后发现错误竟然出现在最开始,二维数组的长和宽搞混了……而且第一组测试数据的长和宽正好一样。。。哇……真的……找了半天……

以后不能犯这种低级错误了……

发现已经有大佬快把练习AK了……感觉自己还是很菜

不过还是稳扎稳打继续努力吧。

附今天另外一个题:

Problem Description

When a radio station is broadcasting over a very large area, repeaters are used to retransmit the signal so that every receiver has a strong signal. However, the channels used by each repeater must be carefully chosen so that nearby repeaters do not interfere
with one another. This condition is satisfied if adjacent repeaters use different channels. 

Since the radio frequency spectrum is a precious resource, the number of channels required by a given network of repeaters should be minimised. You have to write a program that reads in a description of a repeater network and determines the minimum number of
channels required.

 

Input

The input consists of a number of maps of repeater networks. Each map begins with a line containing the number of repeaters. This is between 1 and 26, and the repeaters are referred to by consecutive upper-case letters of the alphabet starting with A. For example,
ten repeaters would have the names A,B,C,...,I and J. A network with zero repeaters indicates the end of input. <br> <br>Following the number of repeaters is a list of adjacency relationships. Each line has the form: <br> <br>A:BCDH <br> <br>which indicates
that the repeaters B, C, D and H are adjacent to the repeater A. The first line describes those adjacent to repeater A, the second those adjacent to B, and so on for all of the repeaters. If a repeater is not adjacent to any other, its line has the form <br>
<br>A: <br> <br>The repeaters are listed in alphabetical order. <br> <br>Note that the adjacency is a symmetric relationship; if A is adjacent to B, then B is necessarily adjacent to A. Also, since the repeaters lie in a plane, the graph formed by connecting
adjacent repeaters does not have any line segments that cross. <br>

 

Output

For each map (except the final one with no repeaters), print a line containing the minumum number of channels needed so that no adjacent channels interfere. The sample output shows the format of this line. Take care that channels is in the singular form when
only one channel is required.

 

Sample Input

2
A:
B:
4
A:BC
B:ACD
C:ABD
D:BC
4
A:BCD
B:ACD
C:ABD
D:ABC
0

 

Sample Output

1 channel needed.
3 channels needed.
4 channels needed.

思路见代码:

/*

 相邻两个中继器不能使用同一个频道。

 用map标记相邻的中继器;

 搜索过程中判断相邻中继器是否使用同一个频道;

 若没有频道可以用,频道增一;

 若全搜索完,则输出需要的频道数;

 */

#include <iostream>

#include <cstring>

#include <algorithm>

using namespace std;

char map[1000][1000];

int visit[2000];

int flag,ans,n;

int pd(int d,int c)

{

    for (int k = 1; k <= n; k++)

        if (map[d][k] == 1 && visit[k] == c)

            return 0;

    return 1;

}

void DFS(int d)

{

    if (flag == 1)

        return;

    if (d == n + 1)

    {

        flag = 1;

        if (ans == 1)

            cout << ans << " channel needed." << endl;

        else

            cout << ans << " channels needed." << endl;

        return ;

    }

    for (int i = 1; i <= ans; i++)

    {

        if (pd(d,i))

        {

            visit[d] = i;

            DFS(d + 1);

            visit[d] = 0;

        }

    }

    ans += 1;

    visit[d] = ans;

    DFS(d + 1);

    visit[d] = 0;

    ans = ans - 1;

    

}

int main()

{

    int i,j;

    string a;

    while(cin >> n)

    {

        if (n == 0)

            break;

        memset(map,0,sizeof(map));

        memset(visit,0,sizeof(visit));

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

        {

            cin >> a;

            if (a.length() > 2)

            {

                for (j = 2; j < a.length(); j++)

                {

                    map[i][a[j] - 'A' + 1] = 1;

                    //   cout << i << " " << a[j] - 'A' + 1 << endl;

                }

            }

        }

        flag = 0;

        ans = 1;

        DFS(1);

    }

    return 0;

}

还是要继续努力……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: