周报4

dfs:

马的遍历

题目描述

 

有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步

 

输入格式

 

一行四个数据,棋盘的大小和马的坐标

 

输出格式

 

一个n*m的矩阵,代表马到达某个点最少要走几步(左对齐,宽5格,不能到达则输出-1)

 

输入输出样例

 

输入 #1
3 3 1 1
输出 #1
0    3    2    
3    -1   1    
2    1    4    
代码
#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
int x, y, hx, hy;
int a[500][500];
void show()
{
    a[hx][hy] = 0;
    for (int i = 1; i <= x; i++)
    {
        for (int j = 1; j <= y; j++)
        {
            printf("%-5d", a[i][j]);
        }
        cout << endl;
    }
}
void bfs()
{
    queue<pair<int, int>> q;
    q.push({ hx,hy });
    while (!q.empty())
    {
        int hhx = q.front().first, hhy = q.front().second; q.pop();
        if (a[hhx + 1][hhy + 2] == 0 && hhx + 1 <= x && hhy + 2 <= y)
        {
            a[hhx + 1][hhy + 2] = a[hhx][hhy] + 1;
            q.push({ hhx + 1 ,hhy + 2 });
        }
        if (a[hhx + 2][hhy + 1] == 0 && hhx + 2 <= x && hhy + 1 <= y)
        {
            a[hhx + 2][hhy + 1] = a[hhx][hhy] + 1;
            q.push({ hhx + 2 ,hhy + 1 });
        }
        if (a[hhx + 2][hhy - 1] == 0 && hhx + 2 <= x && hhy - 1>=1)
        {
            a[hhx + 2][hhy - 1] = a[hhx][hhy] + 1;
            q.push({ hhx + 2 ,hhy -1 });
        }
        if (a[hhx + 1][hhy -2] == 0 && hhx + 1 <= x && hhy - 2 >=1)
        {
            a[hhx + 1][hhy - 2] = a[hhx][hhy] + 1;
            q.push({ hhx + 1 ,hhy - 2 });
        }
        if (a[hhx - 1][hhy - 2] == 0 && hhx - 1 >=1 && hhy - 2 >=1)
        {
            a[hhx - 1][hhy - 2] = a[hhx][hhy] + 1;
            q.push({ hhx - 1 ,hhy - 2 });
        }
        if (a[hhx -2][hhy -1] == 0 && hhx -2 >=1 && hhy -1 >=1)
        {
            a[hhx -2][hhy -1] = a[hhx][hhy] + 1;
            q.push({ hhx -2 ,hhy-1 });
        }
        if (a[hhx -2][hhy + 1] == 0 && hhx -2>=1 && hhy +1 <=y)
        {
            a[hhx -2][hhy +1] = a[hhx][hhy] + 1;
            q.push({ hhx -2 ,hhy +1 });
        }
        if (a[hhx -1][hhy + 2] == 0 && hhx -1 >=1 && hhy + 2 <= y)
        {
            a[hhx -1][hhy + 2] = a[hhx][hhy] + 1;
            q.push({ hhx -1 ,hhy + 2 });
        }
    }
    for (int i = 1; i <= x; i++)
    {
        for (int j = 1; j <= y; j++)
        {
            if (a[i][j] == 0)a[i][j] = -1;
        }
    }
}

int main(void)
{
    cin >> x >> y >> hx >> hy;
    bfs();
    show();
    return 0;
}

 

kkksc03考前临时抱佛脚

题目背景


kkksc03 的大学生活非常的颓废,平时根本不学习。但是,临近期末考试,他必须要开始抱佛脚,以求不挂科。


题目描述


这次期末考试,kkksc03 需要考 44 科。因此要开始刷习题集,每科都有一个习题集,分别有 s_1,s_2,s_3,s_4s1,s2,s3,s4 道题目,完成每道题目需要一些时间,可能不等(A_1,A_2,\ldots,A_{s_1}A1,A2,,As1B_1,B_2,\ldots,B_{s_2}B1,B2,,Bs2C_1,C_2,\ldots,C_{s_3}C1,C2,,Cs3D_1,D_2,\ldots,D_{s_4}D1,D2,,Ds4)。

kkksc03 有一个能力,他的左右两个大脑可以同时计算 22 道不同的题目,但是仅限于同一科。因此,kkksc03 必须一科一科的复习。

由于 kkksc03 还急着去处理洛谷的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。


输入格式


本题包含 55 行数据:第 11 行,为四个正整数 s_1,s_2,s_3,s_4s1,s2,s3,s4

第 22 行,为 A_1,A_2,\ldots,A_{s_1}A1,A2,,As1 共 s_1s1 个数,表示第一科习题集每道题目所消耗的时间。

第 33 行,为 B_1,B_2,\ldots,B_{s_2}B1,B2,,Bs2 共 s_2s2 个数。

第 44 行,为 C_1,C_2,\ldots,C_{s_3}C1,C2,,Cs3 共 s_3s3 个数。

第 55 行,为 D_1,D_2,\ldots,D_{s_4}D1,D2,,Ds4 共 s_4s4 个数,意思均同上。


输出格式


输出一行,为复习完毕最短时间。


输入输出样例


输入 #1
1 2 1 3		
5
4 3
6
2 4 3
输出 #1
20

说明/提示


1\leq s_1,s_2,s_3,s_4\leq 201s1,s2,s3,s420。

1\leq A_1,A_2,\ldots,A_{s_1},B_1,B_2,\ldots,B_{s_2},C_1,C_2,\ldots,C_{s_3},D_1,D_2,\ldots,D_{s_4}\leq601A1,A2,,As1,B1,B2,,Bs2,C1,C2,,Cs3,D1,D2,,Ds460。


#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 10000;
int sum,total,maxtime,nowtime,aong ;
int a[maxn], b[maxn];
void dfs(int cur)
{
    if (cur > total)
    {
        maxtime = max(maxtime, nowtime);
        return;
    }
    if (nowtime + b[cur] <= sum / 2)
    {
        nowtime += b[cur];
        dfs(cur + 1);
        nowtime -= b[cur];
    }
    dfs(cur + 1);
}
int main(void)
{
    for (int i = 0; i <4; i++) cin >> a[i];

    for (int i = 0; i < 4; i++)
    {
        sum = 0;
        nowtime = 0;
        maxtime = 0;
        total = a[i];
        for (int j = 1; j <= a[i]; j++)
        {
            cin >> b[j];
            sum += b[j];
        }
        //maxtime = 0;
        dfs(1);
        aong += (sum - maxtime);
    }
    cout << aong;
    return 0;
}

八皇后 Checker Challenge

题目描述

一个如下的 6 \times 66×6 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

上面的布局可以用序列 2\ 4\ 6\ 1\ 3\ 52 4 6 1 3 5 来描述,第 ii 个数字表示在第 ii 行的相应位置有一个棋子,如下:

行号 1\ 2\ 3\ 4\ 5\ 61 2 3 4 5 6

列号 2\ 4\ 6\ 1\ 3\ 52 4 6 1 3 5

这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
并把它们以上面的序列方法输出,解按字典顺序排列。
请输出前 33 个解。最后一行是解的总个数。

输入格式

一行一个正整数 nn,表示棋盘是 n \times nn×n 大小的。

输出格式

前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

输入输出样例

输入 #1
6
输出 #1
2 4 6 1 3 5
3 6 2 5 1 4
4 1 5 2 6 3
4

说明/提示

【数据范围】
对于 100\%100% 的数据,6 \le n \le 136n13。

题目翻译来自NOCOW。

USACO Training Section 1.5

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int b1[50], b2[50], b3[50],a[50];
int n, ans = 0;

void dfs(int x)
{
    if (x > n)
    {
        ans++;
        if (ans <= 3)
        {
            for (int i = 1; i <= n; i++) printf("%d ", a[i]);
            puts("");
        }
        return;
    }
    for (int i = 1; i <= n; i++)
    {
        if (b1[i] == 0 && b2[x + i] == 0 && b3[x - i + 15] == 0)
        {
            a[x] = i; b1[i] = 1; b2[x + i] = 1; b3[x - i + 15] = 1;
            dfs(x + 1);
            b1[i] = 0; b2[x + i] = 0; b3[x - i + 15] = 0;
        }
    }
}
int main(void)
{
    cin >> n;
    dfs(1);
    cout << ans;
    return 0;
}

 

bfs:

Meteor Shower S


贝茜听说了一个骇人听闻的消息:一场流星雨即将袭击整个农场,由于流星体积过大,它们无法在撞击到地面前燃烧殆尽,届时将会对它撞到的一切东西造成毁灭性的打击。很自然地,贝茜开始担心自己的安全问题。以 Farmer John 牧场中最聪明的奶牛的名誉起誓,她一定要在被流星砸到前,到达一个安全的地方(也就是说,一块不会被任何流星砸到的土地)。如果将牧场放入一个直角坐标系中,贝茜现在的位置是原点,并且,贝茜不能踏上一块被流星砸过的土地。 根据预报,一共有 MM 颗流星 (1\leq M\leq50,000)(1M50,000) 会坠落在农场上,其中第i颗流星会在时刻 T_iTi (0\leq T_i\leq1,000)(0Ti1,000) 砸在坐标为 (X_i, Y_i)(Xi,Yi(0\leq X_i\leq 300(0Xi300,0\leq Y_i\leq300)0Yi300) 的格子里。流星的力量会将它所在的格子,以及周围 44 个相邻的格子都化为焦土,当然贝茜也无法再在这些格子上行走。

贝茜在时刻 00 开始行动,它只能在第一象限中,平行于坐标轴行动,每 11 个时刻中,她能移动到相邻的(一般是 44 个)格子中的任意一个,当然目标格子要没有被烧焦才行。如果一个格子在时刻 tt 被流星撞击或烧焦,那么贝茜只能在 tt 之前的时刻在这个格子里出现。 贝西一开始在(0,0)(0,0)。

请你计算一下,贝茜最少需要多少时间才能到达一个安全的格子。如果不可能到达输出 -11。

Translated by @奆奆的蒟蒻 @跪下叫哥


输入输出样例


输入 #1
4
0 0 2
2 1 2
1 1 2
0 3 5
输出 #1
5

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
const int  maxn = 350;
using namespace std;
struct node
{
    int x, y;
};
queue<node> q;
int base[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };

int main(void)
{
    int  mapp[maxn][maxn], ans[maxn][maxn];
    int n; cin >> n;
    int xx, yy, tt;
    memset(mapp, 0x7f, sizeof(mapp));
    memset(ans, -1, sizeof(ans));
    for (int i = 0; i < n; i++)
    {
        cin >> xx >> yy >> tt;
        mapp[xx][yy] = min(tt, mapp[xx][yy]);
#define MIN(x,y,z) if(x>=0&&y>=0)mapp[x][y] = min(z,mapp[x][y]);
        //MIN(xx, yy, tt);
        for (int j = 0; j < 4; j++)
            MIN(xx + base[j][0], yy + base[j][1],tt);
    }
    q.push(node { 0, 0 });
    ans[0][0] = 0;
    while (!q.empty())
    {
        int x = q.front().x, y = q.front().y; q.pop();
        for (int i = 0; i < 4; i++)
        {
            int ux = x + base[i][0];
            int uy = y + base[i][1];
            if (ux < 0 || uy < 0 || ans[ux][uy] != -1 || ans[x][y] + 1 >= mapp[ux][uy]) continue;
            ans[ux][uy] = ans[x][y] + 1;
            q.push(node{ ux,uy });
            //printf("当牛走到(%d,%d)时,该地的降落时间为%d,已经走了%d步\n", ux, uy, mapp[ux][uy], ans[ux][uy]);
        }
    }
    int res = 100000;
    for (int i = 0; i <= 305; i++)
        for (int j = 0; j <= 305; j++)
            if (mapp[i][j] > 1000 && ans[i][j] != -1)
                res = min(res, ans[i][j]);
    if (res == 100000)puts("-1");
    else printf("%d", res);
    return 0;
}

 

奇怪的电梯

题目描述


呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第ii层楼(1 \le i \le N)(1iN)上有一个数字K_i(0 \le K_i \le N)Ki(0KiN)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3, 3 ,1 ,2 ,53,3,1,2,5代表了K_i(K_1=3,K_2=3,…)Ki(K1=3,K2=3,),从11楼开始。在11楼,按“上”可以到44楼,按“下”是不起作用的,因为没有-22楼。那么,从AA楼到BB楼至少要按几次按钮呢?


输入格式


共二行。

第一行为33个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N)N,A,B(1N200,1A,BN)。

第二行为NN个用空格隔开的非负整数,表示K_iKi


输出格式


一行,即最少按键次数,若无法到达,则输出-11。


输入输出样例


输入 #1
5 1 5
3 3 1 2 5
输出 #1
3
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

int a[201], b[201];
int N, A, B;
int mini = 9999;
int u = 1;
void bfs(int cur)
{
    //if (cur == B) { q = 1; mini = min(mini, ans); return; }
    //else if (cur < 1 || cur > N)return;
    //ans++;
    //dfs(cur + a[cur]);
    //dfs(cur - a[cur]);
    queue<int>q;
    q.push(cur);
    while (!q.empty())
    {
        int t = q.front(); q.pop();
        if (t == B) { printf("%d", b[t]); return; }
        if (t + a[t] <= N && b[t + a[t]] == 0)
        {
            b[t + a[t]] = b[t] + 1;
            q.push(t + a[t]);
        }
        if (t - a[t] >= 1 && b[t - a[t]] == 0)
        {
            b[t - a[t]] = b[t] + 1;
            q.push(t - a[t]);
        }

    }
    printf("-1");
}
int main(void)
{
    cin >> N >> A >> B;
    for (int i = 1; i <= N; i++) cin >> a[i];
    bfs(A);
    return 0;
}

 

递归:

 

外星密码

 

 

题目描述

 

有了防护伞,并不能完全避免 2012 的灾难。地球防卫小队决定去求助外星种族的帮 助。经过很长时间的努力,小队终于收到了外星生命的回信。但是外星人发过来的却是一 串密码。只有解开密码,才能知道外星人给的准确回复。解开密码的第一道工序就是解压 缩密码,外星人对于连续的若干个相同的子串“X”会压缩为“[DX]”的形式(D 是一个整 数且 1≤D≤99),比如说字符串“CBCBCBCB”就压缩为“[4CB]”或者“[2[2CB]]”,类 似于后面这种压缩之后再压缩的称为二重压缩。如果是“[2[2[2CB]]]”则是三重的。现 在我们给你外星人发送的密码,请你对其进行解压缩。

 

输入格式

 

第一行:一个字符串

 

输出格式

 

第一行:一个字符串

 

输入输出样例

 

输入 #1
AC[3FUN]
输出 #1
ACFUNFUNFUN

 

说明/提示

 

【数据范围】

对于 50%的数据:解压后的字符串长度在 1000 以内,最多只有三重压缩。

对于 100%的数据:解压后的字符串长度在 20000 以内,最多只有十重压缩。 对于 100%的数据:保证只包含数字、大写字母、’[‘和’]‘

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
string DG()
{
    string s = "",T;
    char ch; int t;
    while (cin >> ch)
    {
        if (ch == '[')
        {
            cin >> t;
            T =DG();
            while (t--)s += T;
        }
        else if (ch == ']') return s;
        else  s += ch;
    }
    return s;
}

int main(void)
{
    cout << DG();
    return 0;
}

 

 

 

 

 

 

posted @ 2021-02-28 20:56  loliconsk  阅读(116)  评论(0)    收藏  举报