首页 > 其他分享 >AT_abc184_f [ABC184F] Programming Contest 题解

AT_abc184_f [ABC184F] Programming Contest 题解

时间:2024-03-03 15:35:12浏览次数:22  
标签:frac 题解 ll Programming long abc184 搜索 worth define

题目传送门

前置知识

Meet in the middle

解法

  • 非正解
    • 当成超大背包来做,暴力枚举每个数是否进行相加。
    • 时间复杂度为 \(O(2^{n})\)。
    ll p[50],ans=0;
    void dfs(ll x,ll n,ll m,ll worth)
    {
    	if(x==n+1)
    	{
    		if(worth<=m)
    		{
    			ans=max(ans,worth);
    		}
    	}
    	else
    	{
    		if(worth+p[x]<=m)
    		{
    			dfs(x+1,n,m,worth+p[x],worth+p[x]);
    		}
    		dfs(x+1,n,m,worth);
    	}
    }
    int main()
    {
    	ll n,m,i;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		cin>>p[i];
    	}
    	dfs(1,n,m,0);
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 正解
    • 考虑优化搜索过程,使用双向搜索。具体地,对于 \(1 \sim \left\lfloor \frac{n}{2}\right\rfloor\) 进行第一遍搜索,对于得到的价值存到一个 set 里面。对于 \(\left\lfloor \frac{n}{2}\right\rfloor+1 \sim n\) 进行第二遍搜索,对于得到的总和在 set 里面找到满足 \(\le T\) 减去当前总和的最大总和,进行转移即可。
    • 时间复杂度为 \(O(2^{\frac{n}{2}}n)\) 。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
set<ll>vis;
ll p[50],ans=0;
void dfsl(ll x,ll n,ll m,ll worth)
{
    if(x==n+1)
    {
        if(worth<=m)
        {
            vis.insert(worth);
        }
    }
    else
    {
        if(worth+p[x]<=m)
        {
            dfsl(x+1,n,m,worth+p[x]);
        }
        dfsl(x+1,n,m,worth);
    }
}
void dfsr(ll x,ll n,ll m,ll worth)
{
    if(x==n+1)
    {
        if(worth<=m)
        {
            ans=max(ans,worth+(*(--vis.upper_bound(m-worth))));
        }
    }
    else
    {
        if(worth+p[x]<=m)
        {
            dfsr(x+1,n,m,worth+p[x]);
        }
        dfsr(x+1,n,m,worth);
    }
}
int main()
{
    ll n,m,i;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>p[i];
    }
    dfsl(1,n/2,m,0);
    dfsr(n/2+1,n,m,0);
    cout<<ans<<endl;
    return 0;
}

标签:frac,题解,ll,Programming,long,abc184,搜索,worth,define
From: https://www.cnblogs.com/The-Shadow-Dragon/p/18050112

相关文章

  • P2532 [AHOI2012] 树屋阶梯 题解
    P2532[AHOI2012]树屋阶梯题解容易发现答案是卡特兰数,那么考虑证明这一点。考虑从左下角到右上角填满格子。利用动态规划的思想,回忆一下某道\(IOI\)的题目[数字三角形],每个格子的方案都只能由其左边或下边转移而来。可以结合图理解一下。好,刚才这个定义显然很符合卡特兰......
  • CF1931G One-Dimensional Puzzle 题解
    CF1931GOne-DimensionalPuzzle题解题意传送门思路考虑一下怎么入手,发现一个拼图只能接一些拼图(废话但是有用),所以我们可以简单地画出一个链接关系的图,\(u\tov\)表示编号为\(u\)的拼图后面能够接编号为\(v\)的拼图。然后我们发现问题转换为:......
  • AT_joig2021_d 展覧会 2 (Exhibition 2) 题解
    题目传送门前置知识二分答案解法最小值最大,考虑二分答案。关于check函数的书写,比luoguP1182数列分段SectionII多了个对位置的判定,注意对当前是第一次展出时进行特判。代码#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#defineullunsigne......
  • 牛客练习赛122题解A-D
    牛客练习赛122A.黑白配代码:#include<bits/stdc++.h>usingnamespacestd;constintMAXN=1e5+7;constintINF=0x3f3f3f3f;typedeflonglongll;#defineendl"\n"voidsolve(){ intt,n;cin>>t>>n;inta[n+1];while(t--)......
  • CF1934题解
    题解首先拜谢波叔呀,一眼看上去没思路,直到看见了四重循环,大彻大悟。Solution没什么好说的,暴力四重题意大意就是给你一个数,在1,3,6,10,15中取数,使取出的数等于输入的数,求出至少需要用多少个数。求数代码: for(longlongi=0;i<=2;i++){ for(longlongj=0;j<=1;j++){ for(lo......
  • AT_abc169_f Knapsack for All Subsets题解
    如果我们定义\(dp[i][j]\)表示对于前i个字符而言,其子集满足条件的个数。那4么对于一个位置i而言,要么选择它贡献要么不选择,所以\(dp[i][j]=dp[i-1][j-a[i]](j>=a[i])+dp[i-1][j]\),这是每一个\(f(i)\)的函数。然后我们加上所有的\(dp[i][k](i:1到n)ans+=dp[i][k......
  • CF1383A String Transformation 1 题解
    若某一位\(i\)上\(A_i>B_i\),则显然无解。否则,建立并查集,然后遍历字符串,若\(A_i,B_i\)不在一个集合就合并\(A_i\)与\(B_i\),直到只剩下一个集合,此时的合并总次数即为答案。为什么呢?因为将\(A_i,B_i\)合并的操作可以视为等价于将以\(A_i\)开头的连续若干个相同字符均改......
  • 「TFOI R1」Unknown Graph 题解
    这里是出题人题解。\(\text{SolutionOfProblemC:UnknownGraph.}\)题意还是很清晰的,这里就不再赘述题意了。首先如果没有\(q\)的限制,显然有一种贪心思想就是每个点每次选剩余入度最多的与之连边。但是因为限制,就无法保证贪心的正确性。那该怎么办呢?一个大提示:这题是......
  • P3200 [HNOI2009] 有趣的数列 题解
    P3200[HNOI2009]有趣的数列感性地,我们认为在按照数值从小到大填数时每个时刻所填的奇数位的个数\(x\)不小于所填偶数位的个数\(y\)。我们考虑如何证明这一点。性质1:每一个偶数位上的数都要大于它前面所有的数。这一点应当是显然的。性质2:每一个偶数位上的数都不小于它的下......
  • AT_nikkei2019_2_qual_d Shortest Path on a Line 题解
    我们发现,brute-force的复杂度的优化瓶颈主要在建图上。于是我们有一个巧妙的转化:因为所有满足\(L\leS,T\leR\)的所有边\((S,T)\)的长度均为\(C\)。然后题目要求的是\(1\simN\)的最短路。那么在边权相等的情况下,走到的点的编号一定越大越好。于是在所有点对\((......