杂题

1.奇怪的电梯

dfs:


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;

const int N = 205;

int n, a, b,ans = 0x3f3f3f3f,flag;
int k[N];
bool vis[N];

void dfs(int x, int cnt)
{
    if(ans < cnt)return;
    if(x == b)
    {
        flag = true;
        ans = min(ans, cnt);
        return;
    }
    if(x + k[x] <= n && (!vis[x+k[x]]))
    {
        vis[x+k[x]] = true;
        dfs(x+k[x], cnt+1);
        vis[x+k[x]] = false;
    }
    if(x - k[x] > 0 && (!vis[x-k[x]]))
    {
        vis[x-k[x]] = true;
        dfs(x-k[x], cnt+1);
        vis[x-k[x]] = false;
    }
    return;
}
int main()
{
    scanf("%d%d%d",&n, &a, &b);
    for(int i = 1; i <= n; i++)scanf("%d", &k[i]);
    dfs(a,0);
    if(flag)printf("%d\n", ans);
    else printf("-1\n");
    return 0;
}

bfs :

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;

typedef pair<int, int> PII;
const int N = 205;

int k[N], n, a, b;
bool vis[N];

int bfs(int a, int b)
{
    queue<PII>q;
    q.push({a, 0});
    while(q.size())
    {
        PII t = q.front();
        q.pop();
        if(t.first == b)return t.second;
        if(t.first + k[t.first] <= n &&  !vis[t.first + k[t.first]])
        {
            q.push({t.first + k[t.first], t.second + 1});
            vis[t.first + k[t.first]] = true;
        }
        if(t.first - k[t.first] > 0 && !vis[t.first - k[t.first]])
        {
            q.push({t.first - k[t.first], t.second + 1});
            vis[t.first - k[t.first]] = true;
        }
    }
    return -1;
}
int main()
{
    scanf("%d%d%d",&n, &a, &b);
    for(int i = 1;i <= n; i++)scanf("%d", &k[i]);
    int ans = bfs(a, b);
    printf("%d", ans);
    return 0;
}

2.抓住那头牛

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;

const int N = 100005;
bool vis[N];
int n, k, ans;
struct node{
    int x, t;
};
queue<node>q;
void bfs()
{
    vis[n] = true;
    vis[0] = true;//易错点,vis[0]一定要标记
    node now = (node){n, 0};
    q.push(now);
    while(q.size())
    {
        now = q.front();
        q.pop();
        if(now.x == k)
        {
            printf("%d\n", now.t);
            break;
        }
        if(!vis[now.x+1])
        {
            vis[now.x+1] = true;
            q.push((node){now.x+1, now.t+1});
        }
        if(now.x-1 >= 0 && !vis[now.x-1])
        {
            vis[now.x-1] = true;
            q.push((node){now.x-1, now.t+1});
        }
        if(now.x*2 <= 100010 && !vis[now.x*2])
        {
            vis[now.x*2] = true;
            q.push((node){now.x*2, now.t+1});
        }
    }
}
int main()
{
    scanf("%d%d",&n, &k);
    if(k < n)
    {
        printf("%d\n", n-k);
        return 0;
    }
    bfs();
    return 0;
}

3.棋盘问题

//注意边界问题,还有这一层棋子有不放的这种情况
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

const int N = 10;

int n, k;
char m[N][N];
int vis[N];
int ans;
void dfs(int cal, int step)
{
    if(step == k)
    {
        ans++;
        return;
    }
    if(cal >= n)return;
    for(int i = 0;i < n;i++)//摆所有列
    {
        if(m[cal][i] == '#' && !vis[i])
        {
            vis[i] = 1;
            dfs(cal+1, step+1);
            vis[i] = 0;
        }
    }
    dfs(cal+1,step);//这一行不放棋子
    return;
}
int main()
{
    while(1)
    {
        ans = 0;
        memset(vis, 0, sizeof vis);
        scanf("%d%d", &n, &k);
        if(n == -1)break;
        for(int i = 0;i < n;i++)scanf("%s", m[i]);
        dfs(0, 0);
        printf("%d\n", ans);
    }
    return 0;
}

4.棋盘2

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

const int N = 105;
int Map[N][N];
int d[N][N]; //记忆化搜索
int vis[N][N];
int m, n, ans;
int dx[] = {0, 0, 1, -1},dy[] = {1, -1, 0, 0};
void dfs(int x, int y, int flag, int sum)
{
    if(sum >= d[x][y])return;//这是一个剪枝,记忆化
    d[x][y] = sum;
    if(x == m && y == m)
    {
        ans = min(ans, sum);
        return;
    }
    for(int i = 0;i < 4;i++)
    {
        int xx = x+dx[i],yy = y+dy[i];
        if(xx >= 1 && xx <= m && yy >= 1 && yy <= m && !vis[xx][yy])
        {
            vis[xx][yy] = 1;
            if(Map[xx][yy] == -1)
            {
                if(!flag)
                {
                    Map[xx][yy] = Map[x][y];
                    dfs(xx, yy, 1, sum+2);
                    Map[xx][yy] = -1;
                }
            }
            else
            {
                if(Map[xx][yy] == Map[x][y])dfs(xx, yy, 0, sum);
                else dfs(xx, yy, 0, sum+1);
            }
            vis[xx][yy] = 0;//注意回复现场
        }
    }
    return;
}

int main()
{
    scanf("%d%d",&m, &n);
    memset(Map,-1,sizeof Map);
    memset(d,0x3f3f3f3f, sizeof d);
    for(int i = 1;i <= n;i++)
    {
        int x, y, c;
        scanf("%d%d%d",&x, &y, &c);
        Map[x][y] = c;
    }
    ans = 0x3f3f3f3f;
    dfs(1, 1, 0, 0);
    if(ans == 0x3f3f3f3f)printf("-1\n");
    else printf("%d\n",ans);
    return 0;
}

最强对手矩阵

  • 不能使用全局变量const int N = 100010;这样会爆内存,使用vector用多少存多少。
  • o(n^2m)只能过70%样例,过100%样例可以通过矩阵旋转的方法,降低复杂度。
  • vector的反转和普通整型矩阵不同,要注意反转的细节。
#include <bits/stdc++.h>
using namespace std;
 
int main()
{
    int n,m,res = -0x3f3f3f3f;
    scanf("%d%d",&n,&m);
    vector<vector<int>>g(n+1,vector<int>(m+1));
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= m;j++)
            scanf("%d",&g[i][j]);
    if(n < m)
    {
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= m;j++)
                g[i][j]+=g[i-1][j];
        for(int i = 1;i <= n;i++)
            for(int j = i;j <= n;j++)
            {
                int last = 0;
                for(int k = 1;k <= m;k++)
                {
                    last = max(last,0)+g[j][k]-g[i-1][k];
                    res = max(res,last);
                }
            }
        printf("%d\n",res);
    }
    else
    {
        vector<vector<int>>f(m+1,vector<int>(n+1));
        for(int i = 1;i <= m;i++)
            for(int j = 1;j <= n;j++)
                f[i][j] = g[j][i];
        swap(n, m);
        for(int i = 1;i <= n;i++)
            for(int j = 1;j <= m;j++)
            {
                f[i][j] += f[i-1][j];
            }
        for(int i = 1;i <= n;i++)
            for(int j = i;j <= n;j++)
            {
                int last = 0;
                for(int k = 1;k <= m;k++)
                {
                    last = max(last,0)+f[j][k]-f[i-1][k];
                    res = max(res,last);
                }
            }
        printf("%d\n",res);
    }
    return 0;
}

斐波那契

  • 变成变化简,化简使用gcd,
  • gcd实现的时候要用long long,int会出错
#include <bits/stdc++.h>
using namespace std;

int fun(int n)
{
    if(n < 3)return 1;
    else return fun(n-2)+fun(n-1);
}
long long gcd(long long a,long long b)
{
    return b?gcd(b,a%b):a;
}
int main()
{
    double ans = 0;
    long long fenmu = 1,fenzi = 1;
    for(int i = 3;i <= 14;i++)
    {
        if(i > 1)
        {
            fenzi = fenzi*(fun(i)*fun(i-1))+fenmu;
            fenmu = fenmu*(fun(i)*fun(i-1));
            int mod = gcd(fenzi,fenmu);
            fenzi/=mod;fenmu/=mod;

        }
    }
     printf("%lld/%lld\n",fenzi,fenmu);
}
posted @ 2021-04-11 21:41  _YTW  阅读(57)  评论(0)    收藏  举报