[bin神带我飞系列]专题一 搜索入门

来源:互联网 发布:apache参数优化 编辑:程序博客网 时间:2024/06/10 09:13

搜索入门练练练!

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=65959#overview

感谢bin神带我第一次飞飞飞。


A:

题意:

在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。- - 中文题。

解析:

每行往下dfs,水。

代码:

#include <stdio.h>#include <string.h>const int maxn = 10 + 10;char g[maxn][maxn];bool vis[maxn];int ans;int n;void dfs(int row, int k){    if (row == n)    {        if (k == 0)        {            ans++;        }        return ;    }    dfs(row + 1, k);    for (int i = 0; i < n; i++)    {        if (g[row][i] == '#' && !vis[i])        {            vis[i] = true;            dfs(row + 1, k - 1);            vis[i] = false;        }    }    return;}int main(){    #ifdef LOCAL    freopen("in.txt", "r", stdin);    #endif // LOCAL    int k;    while (~scanf("%d%d", &n, &k))    {        if (n == -1 && k == -1)            break;        for (int i = 0; i < n; i++)        {            scanf("%s", g[i]);        }        memset(vis, false, sizeof(vis));        ans = 0;        dfs(0, k);        printf("%d\n", ans);    }    return 0;}

B:

题意:

3D迷宫,bfs。

解析:

加一维表示空间就好惹,从bin神那里学来的step -1 标记法,再也不用vis担心我的搜索重复了。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 30 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int dir[][3] = {{0, -1, 0}, {0, 1, 0}, {-1, 0, 0}, {1, 0, 0}, {0, 0, -1}, {0, 0, 1}};int l, r, c;int g[maxn][maxn][maxn];int dp[maxn][maxn][maxn];struct Node{    int x, y, z;    Node(int _x, int _y, int _z)    {        x = _x;        y = _y;        z = _z;    }};bool ok(int x, int y, int z){    if (0 <= x && x < r && 0 <= y && y < c && 0 <= z && z < l && g[z][x][y] != '#')        return true;    return false;}int bfs(int sx, int sy, int sz, int ex, int ey, int ez){    memset(dp, -1, sizeof(dp));    queue<Node> q;    q.push(Node(sx, sy, sz));    dp[sx][sy][sz] = 0;    while (!q.empty())    {        Node now = q.front();        q.pop();        int x = now.x;        int y = now.y;        int z = now.z;        //cout << x << " " << y << " " << z << endl;        if (x == ex && y == ey && z == ez)        {            return dp[x][y][z];        }        for (int i = 0; i < 6; i++)        {            int nx = x + dir[i][0];            int ny = y + dir[i][1];            int nz = z + dir[i][2];            if (ok(nx, ny, nz))            {                if (dp[nx][ny][nz] == -1)                {                    dp[nx][ny][nz] = dp[x][y][z] + 1;                    q.push(Node(nx, ny, nz));                }            }        }    }    return -1;}int main(){    #ifdef LOCAL    freopen("in.txt", "r", stdin);    #endif // LOCAL    while (~scanf("%d%d%d", &l, &r, &c))    {        if (!l && !r && !c)            break;        getchar();        for (int i = 0; i < l; i++)        {            for (int j = 0; j < r; j++)            {                for (int k = 0; k < c; k++)                {                    scanf("%c", &g[i][j][k]);                }                getchar();            }            getchar();        }        int sx, sy, sz, ex, ey, ez;        for (int i = 0; i < l; i++)        {            for (int j = 0; j < r; j++)            {                for (int k = 0; k < c; k++)                {                    if (g[i][j][k] == 'S')                    {                        sx = j;                        sy = k;                        sz = i;                    }                    if (g[i][j][k] == 'E')                    {                        ex = j;                        ey = k;                        ez = i;                    }                }            }        }       // cout << sx << " " << sy << " " << sz << " " << endl;cout << ex << " " << ey << " " << ez << " " << endl;        int ans = bfs(sx, sy, sz, ex, ey, ez);        if (ans == -1)        {            printf("Trapped!\n");        }        else        {            printf("Escaped in %d minute(s).\n", ans);        }    }    return 0;}

C:

题意:

抓牛,牛在一个位置,你在一个位置,你的坐标可以+1 or -1 or *2,最短抓到牛的时间。

解析:

bfs,加了一点点剪枝。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 100000 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int step[maxn];int bfs(int n, int k){    memset(step, -1, sizeof(step));    queue<int> q;    q.push(n);    step[n] = 0;    while (!q.empty())    {        int now = q.front();        q.pop();        if (now == k)            return step[now];        int next;        /// - 1        next = now - 1;        if (0 <= next && step[next] == -1)///剪枝        {            step[next] = step[now] + 1;            q.push(next);        }        /// + 1        next = now + 1;        if (next < maxn && step[next] == -1)///剪枝        {            step[next] = step[now] + 1;            q.push(next);        }        /// * 2        next = now * 2;        if (next < maxn && step[next] == -1)///剪枝        {            step[next] = step[now] + 1;            q.push(next);        }    }    return 0;}int main(){    #ifdef LOCAL    freopen("in.txt", "r", stdin);    #endif // LOCAL    int n, k;    while (~scanf("%d%d", &n, &k))    {        printf("%d\n", bfs(n, k));    }    return 0;}

D:

题意:

题目看了半天才懂,给一个n*m的01矩阵,0代表白,1代表黑。

现在要你来翻转他们,每次翻转一个点,这个点的上下左右的点都会翻转,1翻成0,0翻转成1。

现在要你求最短的翻转次数,使得这个矩阵全白,that means 全为0。

解析:

参考了网上一些大牛的做法。

首先,如果一个点翻转两次和没翻是没差的,所以一个点最多只翻一次。

n,m并不大,只有15,所以用状态压缩把010101的状态保存下来,然后暴力下去。

为了保证字典序最小,从第一行的右向左开始暴,每次第一行确定了以后,剩下的行的状态也就随之确定了(想一想,为什么)。

然后全部搞完以后,判断最后一行是否全为0,若是,则此次翻转成功,更新最小值,就好啦。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 15 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int dir[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};int n, m;int cnt;int g[maxn][maxn];int t[maxn][maxn];int flipNum[maxn][maxn];void flip(int x, int y){    cnt++;    flipNum[x][y] = 1;    t[x][y] ^= 1;    for (int i = 0; i < 4; i++)    {        int nx = x + dir[i][0];        int ny = y + dir[i][1];        if (0 <= nx && nx < n && 0 <= ny && ny < m)        {            t[nx][ny] ^= 1;        }    }    return;}bool ok(int state){    cnt = 0;    memcpy(t, g, sizeof(t));    for (int i = 0; i < m; i++)    {        if (state & (1 << (m - i - 1)))        {            flip(0, i);        }    }    for (int i = 1; i < n; i++)    {        for (int j = 0; j < m; j++)        {            if (t[i - 1][j])            {                flip(i, j);            }        }    }    for (int i = 0; i < m; i++)    {        if (t[n - 1][i])        {            return false;        }    }    return true;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    while (~scanf("%d%d", &n, &m))    {        for (int i = 0; i < n; i++)        {            for (int j = 0; j < m; j++)            {                scanf("%d", &g[i][j]);            }        }        int ans = n * m + 1;        int state = -1;        memset(flipNum, 0, sizeof(flipNum));        for (int i = 0; i < (1 << m); i++)        {            if (ok(i) && cnt < ans)            {                ans = cnt;                state = i;            }        }        memset(flipNum, 0, sizeof(flipNum));        if (state != -1)        {            ok(state);            for (int i = 0; i < n; i++)            {                for (int j = 0; j < m; j++)                {                    printf("%d%c", flipNum[i][j], j < m - 1 ? ' ' : '\n');                }            }        }        else        {            printf("IMPOSSIBLE\n");        }    }    return 0;}

E:

题意:

给一个数n,求这个数的倍数里面,只含0、1的数。

解析:

看别人暴了一个20位的数,用unsigned __int64水过。

小u的博客上有数论的解法。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long long#define UI64 unsigned __int64using namespace std;const int maxn = 15;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int n;bool flag;void dfs(UI64 t, int dep){    if (flag)        return;    if (dep >= 20)        return;    if (t % n == 0)    {        flag = true;        printf("%I64u\n", t);        return;    }    dfs(t * 10, dep + 1);    dfs(t * 10 + 1, dep + 1);}int main(){    #ifdef LOCAL    freopen("in.txt", "r", stdin);    #endif // LOCAL    while (scanf("%d", &n) && n)    {        flag = false;        dfs(1, 0);    }    return 0;}

F:

题意:

素数路径,给俩素数,每次只能改变一个位置的数,并且改变成的这个数也要是素数,求最少变换次数。

解析:

bfs,素数处理方法,刚开始用数论里面总结的素数打表法竟然出错了,我。。。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 1e4 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int prime[maxn];bool isPrime[maxn];int nprime;void primeTable(){    int i,j;    for(i = 1000; i <= maxn; i++)    {        for(j = 2; j < i; j++)            if(i % j == 0)            {                isPrime[i] = false;                break;            }        if(j == i)            isPrime[i] = true;    }}bool flag;int step[maxn];int bfs(int s, int e){    int num[5];    memset(step, -1, sizeof(step));    queue<int> q;    q.push(s);    step[s] = 0;    while (!q.empty())    {        int now = q.front();        q.pop();        if (now == e)        {            flag = true;            return step[now];        }        int t = now;        for (int i = 0; i < 4; i++)        {            num[i] = t % 10;            t /= 10;        }        for (int i = 0; i < 4; i++)        {            t = num[i];            for (int j = 0; j <= 9; j++)            {                if (j != t)                {                    num[i] = j;                    int next = 0;                    for (int k = 3; k >= 0; k--)                        next = next * 10 + num[k];                    if (step[next] == -1 && isPrime[next])                    {                        step[next] = step[now] + 1;                        q.push(next);                    }                }                num[i] = t;            }        }    }}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    int ncase;    scanf("%d", &ncase);    primeTable();    while (ncase--)    {        int s, e;        scanf("%d%d", &s, &e);        flag = false;        int ans = bfs(s, e);        if (flag)            printf("%d\n", ans);        else            printf("Impossible\n");    }    return 0;}

G:

题意:

又是一道题意题。

给俩字符串,每次洗牌,洗牌规则是交叉交叉交叉,问几次能到达目标串。

解析:

用set来替代Hash判断是否有重复存在。

然后得到这个思路模拟模拟模拟就好了。

具体看代码。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#include <set>#define LL long longusing namespace std;const int maxn = 100 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    int ncase;    scanf("%d", &ncase);    int ca = 1;    set<string> shuf;    string aim, str, s1, s2;    int n;    while (ncase--)    {        cin >> n >> s1 >> s2 >> aim;        str.resize(2 * n);        shuf.clear();        bool found = false;        int cnt = 0;        while (!found)        {            cnt++;            for (int i = 0; i < n; i++)            {                str[i * 2] = s2[i];                str[i * 2 + 1] = s1[i];            }            for (int i = 0; i < n; i++)            {                s1[i] = str[i];                s2[i] = str[i + n];            }            if (str == aim)            {                found = true;                break;            }            if (shuf.find(str) == shuf.end())                shuf.insert(str);            else                break;        }        printf("%d ", ca++);        if (found)            printf("%d\n", cnt);        else            printf("-1\n");    }    return 0;}

H:

题意:

倒水问题,给你无限量的水,两容量分别为a, b的杯子,问你能否倒出 c 状态容量的水。

基本操作有:fill1 ...fill2... drop1 ...drop2 ...pour 1 -> 2... pour 2 -> 1...

解析:

按照题意一路dfs暴下去就好了。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 200 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int a, b, c, ans;string tstring[10000 + 10], astring[1000 + 10];bool flag, vis[100 + 10][100 + 10];void dfs(int x, int y, int dep){    if (ans < dep)        return;    if (x == c || y == c)    {        if (dep < ans)        {            ans = dep;            flag = true;            for (int i = 0; i < ans; i++)                astring[i] = tstring[i];        }    }    //fill 1    if (x < a && !vis[a][y])    {        vis[a][y] = true;        tstring[dep] = "FILL(1)";        dfs(a, y, dep + 1);        vis[a][y] = false;    }    //fill 2    if (y < b && !vis[x][b])    {        vis[x][b] = true;        tstring[dep] = "FILL(2)";        dfs(x, b, dep + 1);        vis[x][b] = false;    }    //drop 1    if (0 < x && !vis[0][y])    {        vis[0][y] = true;        tstring[dep] = "DROP(1)";        dfs(0, y, dep + 1);        vis[0][y] = false;    }    //drop2    if (0 < y && !vis[x][0])    {        vis[x][0] = true;        tstring[dep] = "DROP(2)";        dfs(x, 0, dep + 1);        vis[x][0] = false;    }    //pour 1 -> 2    if (0 < x && y < b)    {        int t;        if (x < b - y)            t = x;        else            t = b - y;        if (!vis[x - t][y + t])        {            vis[x - t][y + t] = true;            tstring[dep] = "POUR(1,2)";            dfs(x - t, y + t, dep + 1);            vis[x - t][y + t] = false;        }    }    //pour 2 -> 1    if (0 < y && x < a)    {        int t;        if (y < a - x)            t = y;        else            t = a - x;        if (!vis[x + t][y - t])        {            vis[x + t][y - t] = true;            tstring[dep] = "POUR(2,1)";            dfs(x + t, y - t, dep + 1);            vis[x + t][y - t] = false;        }    }    return ;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    while (~scanf("%d%d%d", &a, &b, &c))    {        memset(vis, false, sizeof(vis));        vis[0][0] = true;        flag = false;        ans = inf;        dfs(0, 0, 0);        if (flag)        {            printf("%d\n", ans);            for (int i = 0; i < ans; i++)            {                cout << astring[i] << endl;            }        }        else        {            printf("impossible\n");        }    }    return 0;}

I:

题意:

我大fzu的题!鸡冻。

给一张图,图上的#代表一个草,现在你可以hentai的找两个干草点来点燃他们,火势每秒会向上下左右四个方向蔓延。

问最初只点两个草的情况下最快能多快把所有草点燃,若不能输出-1。

解析:

干草点不多,枚举两个#起点来做。

每枚举两个#,就把两个点扔到bfs里面加到队列里,求最短烧完时间。

很显然,要把所有草都点燃,bfs时最后出队列的一定就是时间点了。

然后枚举判断所有#是否都被点燃,若没有,则继续枚举,若有,更新。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 10 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int dir[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};int n, m;char g[maxn][maxn];struct Node{    int x, y;    Node (){}    Node(int _x, int _y)    {        x = _x;        y = _y;    }} p[maxn * maxn];int step[maxn][maxn];int bfs(Node a, Node b){    memset(step, -1, sizeof(step));    int res = 0;    queue<Node> q;    q.push(a);    q.push(b);    step[a.x][a.y] = 0;    step[b.x][b.y] = 0;    while (!q.empty())    {        Node now = q.front();        q.pop();        int x = now.x;        int y = now.y;        res = step[x][y];        for (int i = 0; i < 4; i++)        {            int nx = x + dir[i][0];            int ny = y + dir[i][1];            if (0 <= nx && nx < n && 0 <= ny && ny < m && g[nx][ny] == '#' && step[nx][ny] == -1)            {                step[nx][ny] = step[x][y] + 1;                q.push(Node(nx, ny));            }        }    }    return res;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    int ncase;    int ca = 1;    scanf("%d", &ncase);    while (ncase--)    {        scanf("%d%d", &n, &m);        int cnt = 0;        for (int i = 0; i < n; i++)        {            scanf("%s", g[i]);            for (int j = 0; j < m; j++)            {                if (g[i][j] == '#')                {                    p[cnt].x = i;                    p[cnt++].y = j;                }            }        }        int ans = inf;        for (int i = 0; i < cnt; i++)        {            for (int j = i; j < cnt; j++)            {                int t = bfs(p[i], p[j]);                bool over = true;                for (int k = 0; k < n; k++)                {                    for (int l = 0; l < m; l++)                    {                        if (step[k][l] == -1 && g[k][l] == '#')                        {                            over = false;                            break;                        }                    }                    if (!over)                        break;                }                if (over)                {                    if (t < ans)                        ans = t;                }            }        }        printf("Case %d: ", ca++);        if (ans == inf)        {            printf("-1\n");        }        else        {            printf("%d\n", ans);        }    }    return 0;}

J:

题意:

着火密室逃脱play。

给一张图,图上有不止一个着火点F,和上题一样,每秒火苗会往上下左右蔓延。

现在你,J,站在密室中的一个点,问你能否跑出这片火海。当你到达密室边界的时候就算逃脱成功。

解析:

我用了两次bfs,首先第一次先把fire烧到每个点的时间用fireStep保存下来, 相当于先分析火烧的方向与时间。

然后第二次就轮到你,J,来走了,同样是一步一步往外搜,当下个点的没有被火烧到 || 你到达下个点的时间早于火烧到的时间,就把这个点入队。

最后到达边界再+1你就活了!!

先是把出口的 y == m - 1写成n。。。

然后才发现了F可能不止一个地方开始烧。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 1000 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int dir[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};int n, m;char g[maxn][maxn];int fireStep[maxn][maxn];int joesStep[maxn][maxn];struct Node{    int x, y;    Node(){}    Node(int _x, int _y)    {        x = _x;        y = _y;    }};void fireBfs(){    memset(fireStep, -1, sizeof(fireStep));    queue<Node> q;    ///not only one fire    for (int i = 0; i < n; i++)    {        for (int j = 0; j < m; j++)        {            if (g[i][j] == 'F')            {                q.push(Node(i, j));                fireStep[i][j] = 0;            }        }    }    while (!q.empty())    {        Node now = q.front();        q.pop();        int x = now.x;        int y = now.y;        for (int i = 0; i < 4; i++)        {            int nx = x + dir[i][0];            int ny = y + dir[i][1];            if (0 <= nx && nx < n && 0 <= ny && ny < m && g[nx][ny] != '#' && fireStep[nx][ny] == -1)            {                fireStep[nx][ny] = fireStep[x][y] + 1;                q.push(Node(nx, ny));            }        }    }    return;}int joesBfs(){    memset(joesStep, -1, sizeof(joesStep));    queue<Node> q;    for (int i = 0; i < n; i++)    {        for (int j = 0; j < m; j++)        {            if (g[i][j] == 'J')            {                q.push(Node(i, j));                joesStep[i][j] = 0;                break;            }        }    }    while (!q.empty())    {        Node now = q.front();        q.pop();        int x = now.x;        int y = now.y;        if (x == 0 || x == n - 1 || y == 0 || y == m - 1)        {            return joesStep[x][y] + 1;        }        for (int i = 0; i < 4; i++)        {            int nx = x + dir[i][0];            int ny = y + dir[i][1];            if (0 <= nx && nx < n && 0 <= ny && ny < m && g[nx][ny] != '#')            {                if (joesStep[nx][ny] == -1)                {                    if (fireStep[nx][ny] == -1 || joesStep[x][y] + 1 < fireStep[nx][ny])                    {                        joesStep[nx][ny] = joesStep[x][y] + 1;                        q.push(Node(nx, ny));                    }                }            }        }    }    return -1;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    int ncase;    scanf("%d", &ncase);    while (ncase--)    {        scanf("%d%d", &n, &m);        for (int i = 0; i < n; i++)        {            scanf("%s", g[i]);        }        fireBfs();        int ans = joesBfs();        if (ans == -1)        {            printf("IMPOSSIBLE\n");        }        else        {            printf("%d\n", ans);        }    }    return 0;}

K:

题意:

给一个5*5的01迷宫,让你找从左上点(0, 0)到右下点(4, 4)的最短路径,打印。

解析:

这个迷宫这么小,随便搞吧!

结果,打印路径坑死了。。。

这不是和dp的打印路径很像嘛。。。

但是我用了指针。。。可能数据结构写顺手了。。。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 10 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int dir[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};int g[maxn][maxn];struct Node{    int x, y;    Node* pre;//    Node(int _x, int _y)//    {//        x = _x;//        y = _y;//    }};void print(Node* now){    if (now -> pre != NULL)    {        print(now -> pre);        printf("(%d, %d)\n", now -> x, now -> y);    }}void bfs(int x, int y){    queue<Node*> q;    Node* s = new Node;    g[x][y] = 1;    s -> x = x;    s -> y = y;    s -> pre = NULL;    q.push(s);    while (!q.empty())    {        Node* now = q.front();        q.pop();        int x = now -> x;        int y = now -> y;        //cout << now -> x << " " << now -> y << endl;        if (x == 4 && y == 4)        {          //  cout << "ok" << endl;            printf("(0, 0)\n");            print(now);            return;        }        for (int i = 0; i < 4; i++)        {            int nx = x + dir[i][0];            int ny = y + dir[i][1];            if (0 <= nx && nx < 5 && 0 <= ny && ny < 5 && g[nx][ny] != 1)            {                Node* next = new Node;                g[nx][ny] = 1;                next -> x = nx;                next -> y = ny;                next -> pre = now;                q.push(next);                //cout << q.front() -> x << q.front() -> y << endl;            }        }    }}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    for (int i = 0; i < 5; i++)    {        for (int j = 0; j < 5; j++)        {            scanf("%d", &g[i][j]);        }    }    bfs(0, 0);    return 0;}

L:

题意:

我的入门dfs题,其实是递归。

找八个方向的联通块有多少个。

解析:

枚举@,往下dfs,改@,出联通个数。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 100 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int dir[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};int n, m;char g[maxn][maxn];void dfs(int x, int y){    g[x][y] = '.';    for (int i = 0; i < 8; i++)    {        int nx = x + dir[i][0];        int ny = y + dir[i][1];        if (0 <= nx && nx < n && 0 <= ny && ny < m && g[nx][ny] == '@')        {            dfs(nx, ny);        }    }    return;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    while (scanf("%d%d", &n, &m) == 2)    {        if (!n && !m)            break;        for (int i = 0; i < n; i++)        {            scanf("%s", g[i]);        }        int ans = 0;        for (int i = 0; i < n; i++)        {            for (int j = 0; j < m; j++)            {                if (g[i][j] == '@')                {                    dfs(i, j);                    ans++;                }            }        }        printf("%d\n", ans);    }    return 0;}

M:

题意:

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。

因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。

但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升(正好装满一瓶)

它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。

聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。

中文题~。

解析:

如果s是奇数,直接NO。

然后就和上面那道倒水题异曲同工了,区别只是这题多了个杯子,并且给定了初始水量。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 100 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int a, b, c;int ans;bool vis[maxn][maxn][maxn];int target;void dfs(int x, int y, int z, int dep){    if ((x == target && y == target) || (x == target && z == target) || (y == target && z == target))    {        if (dep < ans)        {            ans = dep;        }        return;    }    //x -> y    if (0 < x && y < b)    {        int t;        if (x < b - y)            t = x;        else            t = b - y;        if (!vis[x - t][y + t][z])        {            vis[x - t][y + t][z] = true;            dfs(x - t, y + t, z, dep + 1);            vis[x - t][y + t][z] = false;        }    }    //y -> x    if (0 < y && x < a)    {        int t;        if (y < a - x)            t = y;        else            t = a - x;        if (!vis[x + t][y - t][z])        {            vis[x + t][y - t][z] = true;            dfs(x + t, y - t, z, dep + 1);            vis[x + t][y - t][z] = false;        }    }    //x -> z    if (0 < x && z < c)    {        int t;        if (x < c - z)            t = x;        else            t = c - z;        if (!vis[x - t][y][z + t])        {            vis[x - t][y][z + t] = true;            dfs(x - t, y, z + t, dep + 1);            vis[x - t][y][z + t] = false;        }    }    //z -> x    if (0 < z && x < a)    {        int t;        if (z < a - x)            t = z;        else            t = a - x;        if (!vis[x + t][y][z - t])        {            vis[x + t][y][z - t] = true;            dfs(x + t, y, z - t, dep + 1);            vis[x + t][y][z - t] = false;        }    }    //y -> z    if (0 < y && z < c)    {        int t;        if (y < c - z)            t = y;        else            t = c - z;        if (!vis[x][y - t][z + t])        {            vis[x][y - t][z + t] = true;            dfs(x, y - t, z + t, dep + 1);            vis[x][y - t][z + t] = false;        }    }    //z -> y    if (0 < z && y < b)    {        int t;        if (z < b - y)            t = z;        else            t = b - y;        if (!vis[x][y + t][z - t])        {            vis[x][y + t][z - t] = true;            dfs(x, y + t, z - t, dep + 1);            vis[x][y + t][z - t] = false;        }    }    return;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    while (~scanf("%d%d%d", &a, &b, &c))    {        if (!a && !b && !c)            break;        if (a % 2)        {            printf("NO\n");        }        else        {            if (b < c)            {                int t = b;                b = c;                c = t;            }            memset(vis, false, sizeof(vis));            ans = inf;            target = a / 2;            vis[a][0][0] = true;            dfs(a, 0, 0, 0);            if (ans == inf)            {                printf("NO\n");            }            else            {                printf("%d\n", ans);            }        }    }    return 0;}

N:

题意:

你Y和你的好基友M,现在想见面,图上有好多家kfc @,现在找到一个kcf,使你到那里的距离+ 你基友到那里的距离最短。

解析:

TLE -> CE -> Wa -> MLE...-> Wa......... -> ac

思路是先用bfs找出你到每个kfc的最短距离,然后再用一次bfs找到你基友到每个kfc的最短距离。

然后遍历一次找最小值就行了。

坑点在于,可能有人到达不了其中的kfc,加的话就-1了。

然后MLE的原因是。。。。我刚开始输入了两次m,n。。。。。还有刚开始写的时候脑子有坑,*11 记成*6,查错查了半天。

代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <climits>#include <cassert>#define LL long longusing namespace std;const int maxn = 200 + 10;const int inf = 0x3f3f3f3f;const double eps = 1e-8;const double pi = acos(-1.0);const double ee = exp(1.0);int dir[][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};int n, m;int step[5][maxn][maxn];char g[maxn][maxn];struct Node{    int x, y;    Node(int _x, int _y)    {        x = _x;        y = _y;    }};void bfs(int sx, int sy, int key){    queue<Node> q;    q.push(Node(sx, sy));    step[key][sx][sy] = 0;    while (!q.empty())    {        Node now = q.front();        q.pop();        int x = now.x;        int y = now.y;        for (int i = 0; i < 4; i++)        {            int nx = x + dir[i][0];            int ny = y + dir[i][1];            if (0 <= nx && nx < n && 0 <= ny && ny < m && g[nx][ny] != '#' && step[key][nx][ny] == -1)            {                step[key][nx][ny] = step[key][x][y] + 1;                q.push(Node(nx, ny));            }        }    }    return;}int main(){#ifdef LOCAL    freopen("in.txt", "r", stdin);#endif // LOCAL    while (scanf("%d%d", &n, &m) == 2)    {        for (int i = 0; i < n; i++)        {            scanf("%s", g[i]);        }        int sx1, sy1, sx2, sy2;        for (int i = 0; i < n; i++)        {            for (int j = 0; j < m; j++)            {                if (g[i][j] == 'Y')                {                    sx1 = i;                    sy1 = j;                }                if (g[i][j] == 'M')                {                    sx2 = i;                    sy2 = j;                }            }        }        memset(step, -1, sizeof(step));        bfs(sx1, sy1, 1);        bfs(sx2, sy2, 2);        int t = inf;        for (int i = 0; i < n; i++)        {            for (int j = 0; j < m; j++)            {                if (g[i][j] == '@'&& step[1][i][j] != -1 && step[2][i][j] != -1)///可能有人到达不了其中的一个kfc                {                    if (step[1][i][j] + step[2][i][j] < t)                        t = step[1][i][j] + step[2][i][j];                }            }        }        printf("%d\n", t * 11);    }    return 0;}



这些题刷了三天,大白还没有继续刷。

接下来搜索进阶估计要刷好几天,加上大白慢慢来吧。

(●—●)。

0 0
原创粉丝点击