一月二十八日总结

P2404 自然数的拆分问题

题目描述

任何一个大于 11 的自然数 n,总可以拆分成若干个小于 n 的自然数之和。现在给你一个自然数 n,要求你求出 n 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。

输入格式

输入:待拆分的自然数 n。

输出格式

输出:若干数的加法式子。

输入输出样例

输入 #1复制

7

输出 #1复制

1+1+1+1+1+1+1
1+1+1+1+1+2
1+1+1+1+3
1+1+1+2+2
1+1+1+4
1+1+2+3
1+1+5
1+2+2+2
1+2+4
1+3+3
1+6
2+2+3
2+5
3+4

说明/提示

数据保证,2≤n≤8。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n, a[10];
void dfs(int sum, int t, int z)
{
    if(sum > n) return;//当搜索到的总和大于n时,序列不符合条件,中断递归

    if(sum == n)//序列满足和等于n时,则按题目格式进行输出
    {
        printf("%d", a[1]);
        for(int i = 2; i < t; i++)    printf("+%d", a[i]);
        printf("\n");
        return;
    }

    for(int i = z; i < n; i++)//防止输出重复的序列,使序列后一个数总大于前一个数
    {
        a[t] = i;//给数组a填充i值,作为序列的每个部分
        dfs(sum + i, t + 1, i);
    }
}

int main()
{
    scanf("%d", &n);

    dfs(0, 1, 1);

    return 0;
}

该题是个典型的dfs问题。最重要的就是熟悉该题dfs的过程并且搞清的dfs()中填入各数的关系。

其他的解释都在注释中。

P2036 [COCI 2008/2009 #2] PERKET

题目描述

Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 n 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 s 和苦度 b。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。

众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。

另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。

输入格式

第一行一个整数 n,表示可供选用的食材种类数。

接下来 n 行,每行 22 个整数 si​ 和 bi​,表示第 i 种食材的酸度和苦度。

输出格式

一行一个整数,表示可能的总酸度和总苦度的最小绝对差。

输入输出样例

输入 #1复制

1
3 10

输出 #1复制

7

输入 #2复制

2
3 8
5 8

输出 #2复制

1

输入 #3复制

4
1 7
2 6
3 8
4 9

输出 #3复制

1

说明/提示

数据规模与约定

对于 100% 的数据,有 1≤n≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1×109,酸度和苦度不同时为 1 和 0。

#include<bits/stdc++.h>
using namespace std;
int min1=2147483647 ;//定义最小值为int的极限
int s[11],b[11];
int n;
void dfs(int i,int a,int d)
{
    if(i>n){//当编号大于n时,则可以终止搜索
        if(a==1&&d==0){//排除所有配料都未选的情况
            return;
        }
        if(abs(a-d)<min1){//比较出最小值
            min1=abs(a-d);
        }
        return;
    }
    dfs(i+1,a*s[i],d+b[i]);//选择编号为i,则酸度苦读按公式增加,进入下一次搜索
    dfs(i+1,a,d);//没有选择编号为i的配料,则酸度与苦度不增加,进入下一次搜索
    return;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d %d",&s[i],&b[i]);//输入第i中配料时的酸度与苦度
    }
    dfs(1,1,0);
    printf("%d",min1);
    return 0;
}

该题是一个经典的搜索树问题。我们通过深搜,进行各编号选与不选的选择,从而实现该题的各种情况。再将各种情况的绝对差进行比较从而得出最小值。但是,要注意将一种配料未选的情况排除。

P1443 马的遍历

题目描述

有一个 n×m 的棋盘,在某个点 (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

输入格式

输入只有一行四个整数,分别为 n,m,x,y。

输出格式

一个 n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 −1−1)。

输入输出样例

输入 #1复制

3 3 1 1

输出 #1复制

0    3    2    
3    -1   1    
2    1    4    

说明/提示

数据规模与约定

对于全部的测试点,保证 1≤x≤n≤400,1≤y≤m≤400。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int a[401][401];
struct point{//定义包含步数的坐标点的结构体
     int x;
     int y;
     int step;
};
int dx[8]={1,2,2,1,-1,-2,-2,-1};
int dy[8]={2,1,-1,-2,-2,-1,1,2};//表示马在棋盘中的各行走方向
int main()
{
    int n,m;
    int p,q;
    scanf("%d %d %d %d",&n,&m,&p,&q);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
              int flag=0;//指示标
              queue<point> r;//定义队列
              struct point start;//表示起点坐标以及步数
              start.x=q;
              start.y=p;
              start.step=0;
              r.push(start);//将起点的结构体压入队列中
              int v[401][401]={0};//初始化指示数组为0
              int min1=99999;//定义一个很大的值,方便求最下值
              while(!r.empty()){//判断队列是否为空队列,是则停止搜索
                   int x1=r.front().x;//提取首队列坐标及步数
                   int y1=r.front().y;
                   int step1=r.front().step;
                if(x1==j&&y1==i){//如果抵达终点
                    flag=1;//指示标赋值为1
                    if(step1<min1){
                        min1=step1;//求最小
                    }
                    break;//终点后终止循环
                }
                for(int i=0;i<8;i++){
                    int tx,ty;
                    tx=x1+dx[i];
                    ty=y1+dy[i];
                    if(tx>=1&&tx<=m&&ty>=1&&ty<=n&&v[tx][ty]==0){//如果下一点未出界且未访问,则执行将下一点坐标压入队列的操作
                    struct point temp;
                    temp.x=tx;
                    temp.y=ty;
                    temp.step=step1+1;
                    r.push(temp);
                    v[tx][ty]=1;//设置为已访问状态
                    }
                }
                r.pop();//将首队列挤出

              }
            if(flag==1){//指示标起判断能否到达的作用
                a[i][j]=min1;。。将最小值带入各矩阵点
            }else{
                a[i][j]=-1;
            }
        }
    }
    for(int i=1;i<=n;i++){//输出最小步数举证
        for(int j=1;j<=m;j++){
            printf("%d\t",a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

该题可用dfs以及bfs的解法。此代码是典型的bfs广搜,注意一下马在棋盘中的行走方式即可。

  • 24
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值