2015 CQUPT WEEKLY TRAINING (1)题解和专题内容推荐

上周讲了栈、队列、DFS、BFS。

有些同学会感到困难,所以对的讲解资料进行推荐。

栈和队列:看PPT就行了,主要理解思想及运用。

DFS,BFS:DFS要深刻理解递归和状态表达,BFS想通状态的层次以及在求一些最小步数、最短路径的题目中运用。

这方面资料除了PPT,还看一下《挑战程序设计竞赛》 这书中的2.1节(P26)和《算法竞赛入门经典》第一版的4.3节(P62)

这两本书在群共享里面都有。

这几个东西一定要理解透彻,后面还会开专题集中训练基础搜索的。


题解:

A、

 题意:1~n顺序进栈,然后给一个序列,判断是否是可能的出栈顺序。

 思路:按照给出的出栈顺序,一个一个和和当前栈顶的元素比较,不相等就向当前栈压入一个元素,因为是按照顺序压栈的,所以总会找到一个当前给出的顺序所在位置值一样的栈顶元素,然后出栈。同时 给出的元素顺序也后移一位  直到给出的顺序遍历完  或者出错。

 参考code:

#include<stdio.h>

int main()
{
    int a[1005],b[1005],i,j,k,n;
    while(scanf("%d",&n),n)
    {
        while(scanf("%d",&b[0]),b[0])
        {
            for(j=1; j<n; j++)
                scanf("%d",&b[j]);
            for(i=1,j=0,k=0; i<=n&&j<n; i++,k++)
            {
                a[k]=i;
                while(a[k]==b[j])
                {
                    if(k>0)k--;
                    else
                    {
                        a[k]=0,k--;
                    }
                    j++;
                    if(k==-1)break;
                }
            }
            if(j==n)printf("Yes\n");
            else printf("No\n");
        }
        printf("\n");
    }
}

B、

题意:对于一个X,支持三种变化:2*X,X-1,X+1。给出A,B 问至少多少步可以从A变成B

思路:很明显的一个BFS题目,挨着搜索一下,并且记录步数。对于搜索范围内设置一个访问数组,已经搜索过的就没必要再从这里搜索了。

参考code:

#include<stdio.h>
#include<climits>
#include<algorithm>
#include<stack>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<string.h>
using namespace std;
int n,k;
int ma=100000;
int vis[100010];
int ret[100010];
int bfs(int n,int k)
{
   if(n==k)
      return 0;
    queue<int> q;
    q.push(n);
    int cur;
    vis[n]=1;
    while(!q.empty())
    {
	   cur=q.front();
	   if(cur==k) break;
	   q.pop();
	   if(cur+1<=100000&&!vis[cur+1])
	   {
		   vis[cur+1]=1;
		   ret[cur+1]=ret[cur]+1;
		   q.push(cur+1);
	   }
	   if(cur-1>=0&&!vis[cur-1])
	   {
		   vis[cur-1]=1;
		   ret[cur-1]=ret[cur]+1;
		   q.push(cur-1);
	   }
	   if(cur*2<=100000&&!vis[cur*2])
	   {
		   vis[cur*2]=1;
		   ret[cur*2]=ret[cur]+1;
		   q.push(cur*2);
	   }
    }
    return ret[k];
}
int  main(void)
{
 	 
 	 while(cin>>n>>k)
 	 {
        ma=100000;
        memset(vis,0,sizeof(vis));
        memset(ret,0,sizeof(ret));
	    cout<<bfs(n,k)<<endl;
     }
 	 return 0;
}

C、

题意:一个棋盘,给出起始坐标和终点左边。需要输出一个最小从起点到终点的方案和步数。

思路:这个题目放在这里,就是让你们坑在固定思维。这道题完全可以不用搜索,直接模拟一下就行了。

参考code:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cassert>
#include <algorithm>
#include <cmath>
#include <set>
#include <limits>
#include <map>

using namespace std;

#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define F(i, n) for(int (i)=0;(i)<(n);++(i))
#define REP(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
#define UREP(i, s, t) for(int (i)=(s);(i)>=(t);--(i))
#define REPOK(i, s, t, o) for(int (i)=(s);(i)<=(t) && (o);++(i))
#define MEM0(addr) memset((addr), 0, sizeof((addr)))

#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398

#define MAXN 100000
#define MAXM 10000
#define MOD 1000000007

typedef long long LL;

const double maxdouble = numeric_limits<double>::max();
const double eps = 1e-10;
const int INF = 0x7FFFFFFF;


char a[5],b[5];
int main()
{
    int l,c;
    while(cin>>a>>b)
    {
        char m,n;
        l=a[0]-b[0];
        c=a[1]-b[1];
        if(l<0)
        {
            l=-l;
            m='R';
        }
        else
            m='L';
        if(c<0)
        {
            c=-c;
            n='U';
        }
        else
            n='D';
        printf("%d\n",max(l,c));
        while(l|c)
        {
            if(l)
            {
                putchar(m);
                l--;
            }
            if(c)
            {
                putchar(n);
                c--;
            }
            printf("\n");
        }
    }
    return 0;
}



D题:强行灌水的。不说了。


E、

题意:就是找出油田中的联通的块数,相邻指的周围的8个位置。

思路:就是一个DFS,详细见代码。这个是DFS的入门例题。

参考code:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>

using namespace std;

const int mxn = (int)105;
int n, m, ans;
int u[] = {-1, -1, -1, 0, 0, 1, 1, 1}, v[] = {-1, 0, 1, -1, 1, -1, 0, 1};
char a[mxn][mxn];

int inb(int x, int y) {
  return (x < 0 || x >= n || y < 0 || y >= m)? 0: 1;
}

void dfs(int x, int y) {
  a[x][y] = '*';
  for (int i = 0; i < 8; i++) {
    int X = x + u[i], Y = y + v[i];
    if (!inb(X, Y) || a[X][Y] == '*') continue;
    dfs(X, Y);
  }
}

int main() {
  while (~scanf("%d %d", &n, &m) && n) {
    ans = 0;
    for (int i = 0; i < n; i++) {
      scanf("%s", a[i]);
    }
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < m; j++) {
        if (a[i][j] == '@') {
          ans++;
          dfs(i, j);
        }
      }
    }
    printf("%d\n", ans);
  }
  return 0;
}

F、

题意:给一个数n,求出一个只由0,1组成的十进制数,使n能整除这个数。

思路:范围不大。搜索一下,看代码比较容易懂。

参考code:

#include<iostream>
#include<cstdio>

using namespace std;
bool flag;
void DFS(unsigned __int64 t ,int n,int k)
{
     if(flag)
         return;
     if(t%n==0)
     {
         printf("%I64u\n",t);
         flag=true;
         return;
     }
     if(k==19)
         return;
     DFS(t*10,n,k+1);
     DFS(t*10+1,n,k+1);
}
int main()
{
    int n;
    while(cin>>n,n)
    {
         flag=false;
         DFS(1,n,0);
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值