Map_纪中1281_dfs

66 篇文章 0 订阅

题目描述


纸条终于传到了Z的手上。这个秘密是什么呢?
原来D发现了一些小纸片,这些纵向长度不一,横向长度都为1个单位长度的小纸片是从一张地图上剪下来的,由于地图有磨损,D无法通过纸片上的图案将完整的地图拼出来,所以她向Z求助。
经过Z的分析,这张地图是一个完整的矩形,并且它的长宽是一定的。Z确信一旦长宽确定,她就能把地图拼出来。
现在,D分析出绘制这张地图的人会用横向尽可能长,纵向尽可能窄的短卷式纸张。她向你求助,希望知道这张地图的横向和纵向长度(其中横向长度尽可能长,纵向长度尽可能短)。

输入


共2行。
第1行,一个整数n,表示纸片数量(1≤n≤60)。
第2行,n个整数,表示各张纸片的纵向长度(1≤l≤50)。

输出


共2行。
第1行,一个整数表示地图的横向长度。
第2行,一个整数表示地图的纵向长度。

题解


题目实际上是要求我们把给定数字分成和相同的几组,组数尽量多
直接上dfs会TLE
剪枝:

  1. 因为一定是矩形,所以只需要枚纸条长度和的约数
  2. 题目要求最大,那么找到第一个就可以退了
  3. 只需要判断是否存在

然而一坨优化比不上媳妇随手的cpp

Code


#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
int num[61],l[61],n,x=0,sum=0;
bool flag;
bool cmp(int a,int b)
{
    return a>b;
}
void dfs(int now,int dep,int lim)
{
    if (now>lim||flag)
        return;
    if (dep>n)
    {
        for (int i=1;i<now;i++)
            if (l[i]!=sum/lim)
                return;
        x=sum/lim;
        flag=true;
        return;
    }
    for (int i=1;i<=now;i++)
        if (l[i]+num[dep]<=sum/lim)
        {
            l[i]+=num[dep];
            dfs(now,dep+1,lim);
            l[i]-=num[dep];
        }
    l[now+1]=num[dep];
    dfs(now+1,dep+1,lim);
    l[now+1]=0;
}
int main()
{
    freopen("map.in","r",stdin);
    freopen("map.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&num[i]);
        sum+=num[i];
    }
    sort(num+1,num+n+1,cmp);
    for (int mid=(int)sqrt(sum);mid>=1;mid--)
        if (sum/mid*mid==sum)
        {
            flag=false;
            dfs(1,1,mid);
            if (flag)
                break;
        }
    printf("%d\n%d\n",sum/x,x);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值