首页 > 其他 > 详细

[洛谷题解]P1025-数的划分

时间:2018-09-20 10:23:51      阅读:133      评论:0      收藏:0      [点我收藏+]

0 前言

啊呀呀终于有时间写博客啦,题解呢,只有在这里才能水一水,所以以后要抓紧时间水啦(今天太困了就不水了)

1 题目部分

懒得复制粘贴了,点这里跳转.

2 题解

2.1 简单的思路

dfs.

选数.从第一个数开始枚举,一直枚举到第n个,每个从1个开始放,到放n个.然后判断和是不是等于m就可以啦

2.2 一个严重的问题 - 判断重复

这个problem让人很讨厌.因为你的判断中不能直接÷3,也不能判断每两个数是否相等,因为1 1 1就是一个反例.

那么,问题来了,怎么判断重复呢?

方法就是让这些数必须为升序,举个栗子:

1 1 5

1 5 1

5 1 1

因为1 5 1不是升序排除,151排除,511排除
则只剩下1 1 5 解决问题.(想了1year)

2.3 代码部分

思路想完了那就上代码吧:

#include <iostream>
using namespace std;
int n,m;
int a[100000];
int b[100000];
int vis[100000];
int c;
void dfs(int x,int last)
{
         
     if(x==n+1)
     {
         int all=0;
         for(int i=1;i<=x;i++)all=all+b[i];
          if(all!=m)return ;
         for(int i=1;i<x-1;i++)
         {
             for(int j=i+1;j<x;j++)
             {
                 
                 if(b[j]<b[i])return ;
             }
         }
     c++;
         return ;
     }
     for(int i=1;i<=m;i++)
     {
         b[x]=i;
         vis[i]=1;
         dfs(x+1,i);
         vis[i]=0;    
         b[x]=0;
        
         
     }
}
int main()
{

        cin>>m>>n;
        c=0;
        dfs(1,0);
        cout<<c<<endl; 

    return 0;
}

 

 那么我们就提交吧,神奇,只得了40分其他TLE.

2.3 改进

好吧,只能剪枝了.如何剪枝呢反正我不知道

首先让人先想到的是

下一个数必定要大于这个数,也就是说a[x+1]>a[x],所以for可以从a[x]一直到n这就是第一个剪枝,好吧那我们把代码写下来吧:

// luogu-judger-enable-o2
// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include <iostream>
using namespace std;
int n,m;
int a[100000];
int b[100000];
int vis[100000];
int c;
void dfs(int x,int last)
{
         
     if(x==n+1)
     {
         int all=0;
         for(int i=1;i<=x;i++)all=all+b[i];
          if(all!=m)return ;
         for(int i=1;i<x-1;i++)
         {
             for(int j=i+1;j<x;j++)
             {
                 
                 if(b[j]<b[i])return ;
             }
         }
     c++;
         return ;
     }
     for(int i=b[x-1];i<=m;i++)
     {
         
         b[x]=i;
         vis[i]=1;
         dfs(x+1,i);
         vis[i]=0;    
         b[x]=0;
        
         
     }
}
int main()
{

        cin>>m>>n;
        c=0;
        b[0]=1;
        dfs(1,0);
        cout<<c<<endl; 

    return 0;
}

提交~多对了一个点,那好吧我们还得继续改进

2.4 继续改进

好吧。我们得继续剪枝,我们做一个统计就是all,all要最后算,我们是不是可以先算呢.也就是说
在x==n+1的时候我们只用判断all是不是等于m,就少了一个for

第二我们在后面增加all,加判断all>m?如果大于了肯定就不是了,下面就上AC代码

2.5 终于通过了

#include <iostream>
using namespace std;
int n,m;
int b[100000];
int vis[100000];
int c;
int all=0;
void dfs(int x,int last)
{
         
     if(x==n+1)
     {
         if(all!=m)return ;
     c++;
         return ;
     }
     for(int i=b[x-1];i+all<=m;i++)
     {
         
         b[x]=i;
         vis[i]=1;
         all=all+i;
         if(all>m)return ;
         dfs(x+1,i);
         vis[i]=0;
         all=all-i;    
         b[x]=0;
        
         
     }
}
int main()
{

        cin>>m>>n;
        c=0;
        b[0]=1;
        dfs(1,0);
        cout<<c<<endl; 

    return 0;
}

bula bula bula ac 100

 

-The end-

-by sffy

[洛谷题解]P1025-数的划分

原文:https://www.cnblogs.com/sffy/p/9677734.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!