zoukankan      html  css  js  c++  java
  • P1466 集合 Subset Sums 搜索+递推+背包三种做法

    题目描述
    对于从1到N (1 <= N <= 39) 的连续整数集合,能划分成两个子集合,且保证每个集合的数字和是相等的。举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,每个子集合的所有数字和是相等的:

    {3} 和 {1,2}

    这是唯一一种分法(交换集合位置被认为是同一种划分方案,因此不会增加划分方案总数) 如果N=7,有四种方法能划分集合{1,2,3,4,5,6,7},每一种分法的子集合各数字和是相等的:

    {1,6,7} 和 {2,3,4,5} {注 1+6+7=2+3+4+5}
    {2,5,7} 和 {1,3,4,6}
    {3,4,7} 和 {1,2,5,6}
    {1,2,4,7} 和 {3,5,6}
    给出N,你的程序应该输出划分方案总数,如果不存在这样的划分方案,则输出0。程序不能预存结果直接输出(不能打表)。
    输入输出格式
    输入格式:
    输入文件只有一行,且只有一个整数N

    输出格式:
    输出划分方案总数,如果不存在则输出0。

    输入输出样例
    输入样例#1:
    7
    输出样例#1:
    4
    说明
    翻译来自NOCOW

    USACO 2.2

    先是搜索,已经确认了当大于28的时候就超时了,所以搜索算是一种方法,不过可以用搜索打表。然后是递推,搜索是不断地递归,所以通过搜索可以改写出递推来,但是会发现有点像背包,索性写个背包出来。

    //DFS
    #include<bits/stdc++.h>
    using namespace std;
    void dfs(int i,int su);
    int sum;
    int ans;
    int n;
    int main()
    {
        cin>>n;
        ans=0;
        sum=(1+n)*n>>1;
        if((sum>>1)*2!=sum)
        {
            cout<<0<<endl;
            return 0;
        }
        dfs(-1,0);
        cout<<(ans>>1)<<endl;
    }
    void dfs(int i,int su)
    {
        for(int j=i+1; j<n; j++)
        {
            if(su+j+1>sum>>1)return ;
            if(su+j+1==sum/2){
                ans++;
                return ;
            }
            dfs(j,su+j+1);
        }
    }
    
    
    //递推
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        int n;
        scanf("%d",&n);
        int sum=(n*(n+1))>>1;
     	 if((sum>>1)<<1!=sum){cout<<0;return 0;}
        long long a[(sum>>1)+1];
        memset(a,0,sizeof(a));
        a[0]=1;
        for(int i=1;i<=n;i++)
            for(int j=sum/2;j>=i;j--)
                a[j]+=a[j-i];
        printf("%d
    ",a[sum>>1]>>1);
        return 0;
    }
    
    // 背包
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int M=1e3+5;
    LL b[M];
    int n;
    LL ans;
    int main(){
        scanf("%d",&n);
        int sum=(n*(n+1))>>1;
     	 if((sum>>1)<<1!=sum){cout<<0;return 0;}
            for(int i=0;i<(1<<(n/2));++i){
                int cur=0;
                for(int j=0;(i>>j)>0;++j)if((i>>j)&1)cur+=(j+1);
                b[cur]++;
            }
            for(int i=0;i<(1<<(n-n/2));++i){
                int cur=0;
                for(int j=0;(i>>j)>0;++j)if((i>>j)&1)cur+=j+n/2+1;
                if((1+n)*n/4>=cur)
                ans+=b[(1+n)*n/4-cur];
            }
            printf("%lld
    ",ans>>1);
        return 0;
    }
    
    
  • 相关阅读:
    视频直播:Windows中各类画面源的截取和合成方法总结
    短视频技术详解:Android端的短视频开发技术
    视频直播关键技术:流畅、拥塞和延时追赶
    视频直播技术详解:直播的推流调度
    直播技术:从性能参数到业务大数据,浅谈直播CDN服务监控
    音视频通话:小议音频处理与压缩技术
    pip命令报错“no perl script found in input”
    python常见面试题讲解(三)明明的随机数
    如何使用photoshop修改图片的像素大小(分辨率)
    VMware Workstation如何修改弹出释放快捷键
  • 原文地址:https://www.cnblogs.com/lunatic-talent/p/12798850.html
Copyright © 2011-2022 走看看