【超基础算法】课程测验——01背包模板题、八皇后、基础搜索题

作者参加了一次算法实践课程的期末测验,通过三道题目的解答过程,反思了自己在算法学习上的不足之处,并分享了AC代码。

今天晚上参加了《算法实践课程》的期末测验。

作为半吊子的废物ACMer,课程学习的内容以及测验的内容着实十分简单。

但是,自己太久没有敲代码、不端正的态度、薄弱的技术功底、废物的数学思维,导致即使是这么简单的题目,我也没有做到快速的20分钟A一题的速度。我觉得自己需要反省,总结自己失败的原因,顺便贴一下自己的代码吧。


考题与答题情况:

第一题:一毛一样除了题面和故事改了一下,就是一道赤裸的01背包问题。但是写完代码,WA了一发。

第二题:从小到大输出N皇后的解,一道非常基础的DFS问题。WA了一发。

第三题:一道很简单的BFS问题,输出最小解的值。


错误原因:

第一题: 背包问题要尽量写成,下标从1开始,否则写递推式的时候,循环里面的j-1部分就不好写,容易有错误。

    以及如果这么写,输入数据的下标也是从1始,我错就错在这两点上。下标习惯从0开始计数了,还没加特判。。。

第二题: 数学没学好。八皇后上下左右判断很简单,只需要判断两个点是x1!=x2&&y1!=y2即可。

    但是斜着的判断,更方便的判断方法是    abs(x1-x2)!=abs(y1-y2)

    而我错误的写法是,abs(x1-y1)!=abs(x2-y2) ,就这一个错误,搞得要死要活。

第三题还好,没错就A了。但是我用的是DFS,而不是最应该想到的BFS。可能还是我思维僵硬,DFS用的太多了,这样对于BFS类的问题就不够活跃。


失败折射:

    失败不是说我没有AC。我觉得失败的原因是,我AC的不够快,思维不够强,编码能下降太多,对自己的要求也下降了太多。今天晚上只是从非常简单的算法题角度,以编码的方式给我敲响了警钟。

    虽然说距离当初的训练刷题时间已经过去1年多了,但是很多基础的东西自己那么快就忘了就是不应该的。作为计算机专业的学生,还是要多加以学习新知识、温习活知识、巩固旧知识呐。


接下来是本次题目的题面:

第一题:

Description

小K是个苦命的孩子,他的师傅为了多赚钱,以减肥为理由,让他去采药,并说不完成不能吃饭。野地里有许多不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。要求在规定的时间t里,采到的草药的总价值最大。


Input

第一行有2个整数T(1≤T≤1000)和M(1≤M≤100),一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。

接下来的M行每行包括两个在1到100之间包括1和100)的整数,分别表示采摘某株草药的时间和这株草药的价值。


Output

1个整数,表示在规定的时间内可以采到的草药的最大总价值。


Sample Input

70 371 10069 11 2

Sample Output

3

个人AC代码(01背包):

#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
#define inf 999
#define loop(x,y,z) for(x=y;x<z;x++)

int n,m;//n是个数,m是背包
int dp[inf][1200];
struct Node
{
    int v,cost;
}node[inf];;

void input()
{
    scanf("%d%d",&m,&n);
    int i;
    loop(i,1,n+1)
        scanf("%d%d",&node[i].cost,&node[i].v);
}

void cal_ans()
{
    memset(dp,0,sizeof dp);
    int i,j;
    loop(i,1,m+1)
        loop(j,1,n+1)
        {
            dp[i][j]=dp[i][j-1];
            if(i-node[j].cost>=0)
                dp[i][j]=max(dp[i][j-1],dp[i-node[j].cost][j-1]+node[j].v);
        }
}

void output()
{
    printf("%d\n",dp[m][n]);
}

int main()
{
    input();
    cal_ans();
    output();
    return 0;
}

第二题:

Description

N皇后的排列,每行一个不冲突;N<=13。


Input

一个数字N (6 <= N <= 13) 表示棋盘是N x N大小的。


Output

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

解的输出顺序为从上到下从左到右,小的优先输出


Sample Input

6

Sample Output

2 4 6 1 3 53 6 2 5 1 44 1 5 2 6 34

个人AC代码(DFS):

#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
#define inf 15
#define INF 999999999
#define loop(x,y,z) for(x=y;x<z;x++)
//下标从0始

int n,sum;
int e[inf];//搜索使用的数组

struct Node
{
    int ans[inf];
    void print()
    {
        int i;
        loop(i,0,n-1)
            printf("%d ",ans[i]+1);
        printf("%d\n",ans[i]+1);
    }
    void set()
    {
        int i;
        loop(i,0,n)
            ans[i]=e[i];
    }
}Ans[5000];

void input()
{
    scanf("%d",&n);
    memset(Ans,0,sizeof Ans);//初始化
    sum=0;
}

bool isLegal(int x1,int y1)//皇后位置是否合法
{
    int i;
    loop(i,0,x1)
    {
        int x2=i;
        int y2=e[i];
        if(x1==x2||y1==y2||abs(x1-x2)==abs(y1-y2))//数学要好好学
            return false;
    }
    return true;
}

void dfs(int i)//第v行
{
    if(i==n)//终止
    {
        if(sum<5)
            Ans[sum].set();
        sum++;
        return ;
    }
    //否则
    int j;
    loop(j,0,n)
    {
        if(isLegal(i,j))//如果在此行可放
        {
            e[i]=j;
            dfs(i+1);//下一行
        }
    }
}

void output()
{

    int i;
    loop(i,0,3)
    {
        Ans[i].print();
    }
    printf("%d\n",sum);
}

int main()
{
    input();
    dfs(0);
    output();
    return 0;
}

第三题:

Description

有个电梯,每一层楼都可以停,只是算法混乱了,所以你得写个补丁;第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N),表示上或下的层数(相对于当前层),每层楼都可以上或下。当然,如果不能满足要求(没有的层),相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(在第一层可以上或下3层;当然下是不可能的,第三层可以上或下1层),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮?

Input

共二行。
第一行为3个用空格隔开的正整数,表示 N,A,B(共基层,开始层,结束层);(1≤N≤200, 1≤A,B≤N)N,A,B(1≤N≤200,1≤A,B≤N)。
第二行为N个用空格隔开的非负整数,表示每层按钮的数值Ki。 

Output

一行,即最少按键次数;若无法到达,则输出−1。

Sample Input

5 1 5
3 3 1 2 5

Sample Output

3

个人AC代码(DFS):

#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
#define inf 250
#define INF 999999999
#define loop(x,y,z) for(x=y;x<z;x++)
//下标从1开始
int n,a,b;
int e[inf];//输入
int book[inf];//标记楼层
int ans;
void input()
{
    scanf("%d%d%d",&n,&a,&b);
    int i;
    loop(i,1,n+1)
        scanf("%d",&e[i]);

    ans=INF;//初始化
    memset(book,0,sizeof book);
}

void dfs(int v,int cost)
{
    if(cost>ans||book[v])return;//剪枝:无意义或者走过
    if(v==b)//到达目的地
    {
        ans=min(ans,cost);
        return;
    }
    //如果未走过
    book[v]=1;

    //向上走
    if(v+e[v]<=n)
        dfs(v+e[v],cost+1);

    //向下走
    if(v-e[v]>=1)
        dfs(v-e[v],cost+1);
}

void output()
{
    if(ans==INF)
        printf("-1\n");
    else
        printf("%d\n",ans);
}

int main()
{
    input();
    dfs(a,0);//从a开始,耗费为0
    output();
    return 0;
}


个人AC代码(BFS):
#include<bits/stdc++.h>
using namespace std;
int e[300];
int book[300];
int n,a,b;

struct Node
{
    int order;
    int value;
    Node(int v,int o):value(v),order(o)
    {

    }
};

int main()
{
    scanf("%d%d%d",&n,&a,&b);
    for(int i=1;i<=n;i++)
        scanf("%d",&e[i]);

    memset(book,0,sizeof book);
    queue<Node>q;
    while(!q.empty())q.pop();
    q.push(Node(a,0));//起点

    while(!q.empty())
    {
        Node v=q.front();
        q.pop();
        book[v.value]=1;

        if(v.value==b)
        {
            printf("%d\n",v.order);
            break;
        }

        //up
        int u=v.value+e[v.value];
        if(u<=n&&!book[u])
        {
            book[u]=1;
            q.push(Node(u,v.order+1));
        }

        //down
        u=v.value-e[v.value];
        if(u>=1&&!book[u])
        {
            book[u]=1;
            q.push(Node(u,v.order+1));
        }
    }

    if(!book[b])
        printf("-1\n");

    return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值