码迷,mamicode.com
首页 > 其他好文 > 详细

习题:小奇取石子(分类讨论)

时间:2019-11-11 21:36:15      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:dfs   没有   iostream   ace   syn   include   using   ref   直接   

题目

传送门

思路

考场上没有仔细看数据范围,导致疯狂爆炸
正解是分类讨论
也就是指对于不同的数据范围,选择不同的解法
手动滑稽
对于前\(70\%\)的数据
直接\(O(2^n)\)
对于后\(30\%\)的数据选择DP
\(dp[i][j][k]\)表示前i个选j堆是否能构成k
很明显i那一位可以直接省去
之后转移即可

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int n,m,K;
int ans=-1;
int a[205];
bool dp[205][2505];//取i堆,j的石子
bool vis[105];
void dfs(int u,int don,int step)
{
    if(don>m||step>K)
        return;
    ans=max(ans,step);
    if(u>n)
        return;
    dfs(u+1,don,step);
    dfs(u+1,don+1,step+a[u]);
}
int main()
{
    ios::sync_with_stdio(false);
    //freopen("stone.in","r",stdin);
    //freopen("stone.out","w",stdout);
    cin>>n>>m>>K;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(a[i]<=K)
            ans=max(a[i],ans);
    }
    if(n<=20)
    {
        dfs(1,0,0);
        cout<<ans;
        return 0;
    }
    dp[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>K)
            continue;
        for(int j=m;j>=1;j--)
        {
            for(int k=K;k>=a[i];k--)
            {
                dp[j][k]|=dp[j-1][k-a[i]];
                if(dp[j][k])
                    ans=max(ans,k);
            }
        }
    }
    cout<<ans;
    return 0;
}

习题:小奇取石子(分类讨论)

标签:dfs   没有   iostream   ace   syn   include   using   ref   直接   

原文地址:https://www.cnblogs.com/loney-s/p/11838345.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!