swjtuoj月赛 C题 (dfs+剪枝)

【cf 487C】【数论+构造】【根据前缀积取模构造序列】

传送门:

http://swjtuoj.handsomehow.com/problem/28/

思路:

暴搜+剪枝即可

通过下列裁剪会加快运算速度

1.将狗粮总数/4,不能整除直接输出no

2.如果有比平均数大的,直接输出no

3.dfs时如果前3个满足,则最后一个一定满足

ps:搜索,dp,数学这些基础内容要加大力度练!!!

代码:

#include <set>
#include <map>
#include <queue>
#include <vector>
#include <math.h>
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using  namespace  std;

#define ff first
#define ss second
#define pb push_back
#define ll long long
#define mod 1000000007
#define ull unsigned long long
#define mst(ss,b) memset(ss,b,sizeof(ss));
#define pl(x) cout << #x << "= " << x << endl;
const int inf = 0x3f3f3f3f;
const int N = 1e5+5;

int n, a[25], ave;
bool vis[25];

bool dfs(int id, int sum, int div){
    if(sum == ave){
        id = sum = 0;
        div++;
        if(div == 3)return 1;
    }
    for(int i=id; i<=n; i++){
        if(!vis[i]){
            if(sum+a[i] <= ave){
                vis[i] = 1;
                if(dfs(i+1, sum+a[i], div))return 1;
                vis[i] = 0;
            }
        }
    }
    return 0;
}

int  main(){
    int T;
    scanf("%d", &T);
    while(T--){
        mst(vis, 0);
        scanf("%d", &n);
        int mx = 0, sum = 0;
        for(int i=1; i<=n; i++)scanf("%d", &a[i]), sum += a[i], mx = max(mx, a[i]);
        ave = sum/4;
        if(sum % 4 || mx>ave)puts("no");
        else{
            if(dfs(1, 0, 0))puts("yes");
            else puts("no");
        }
    }
    return 0;
}

描述:

分狗粮
发布时间: 2017年3月18日 17:14 最后更新: 2017年3月18日 17:17 时间限制: 2000ms 内存限制: 128M

描述
今天handsomehow给大家发了n包狗粮,每一包狗粮里面装有a颗狗粮.而现在你需要把这n包狗粮平均分成4份,以便你和你的室友享用,并且不能把包装给拆开.问你是否能够平均分给你的室友,并且没有剩余?

输入
第一行是一个整数T,表示数据组数.
接下来有T组数据.
每组数据的开头是一个整数n(4<=n<=20),表示有n包狗粮,接着n个数代表每包狗粮的颗数.
保证每包狗粮的颗数a满足条件1<=a<=10,000

输出
如果能够均分一行输出yes
否则输出一行no

样例输入1 复制
2
6 1 1 1 1 1 3
9 1 7 2 2 6 3 5 4 2
样例输出1
no
yes
提示
对于第二组数据,你可以这样分(1,7),(2,6),(3,5),(2,4,2),刚好每人8颗.

对于第一组数据,你不能将他们平均分成4堆.(将会有剩余)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值