您的位置:首页 > 其它

【codevs1039】01年noip TG--数的划分满分dp+愚蠢深搜+pas的奇怪做法

2015-08-08 17:12 330 查看
将整数n分成k份,且每份不能为空,任意两种划分方案不能相同(不考虑顺序)。

例如:n=7,k=3,下面三种划分方案被认为是相同的。

1 1 5

1 5 1

5 1 1

问有多少种不同的分法。

输入:n,k (6<n<=200,2<=k<=6)

输出:一个整数,即不同的分法。

样例in:7
3

样例out:4

先说一下比较蠢(wo de)的做法,直接回溯,由于不知道怎么加优化然后就只得了80,最后一个数据取了极限值,1s内过不了╮(╯▽╰)╭

这段代码是通过前数比后数大来避免重复,但由于时间复杂度为指数级,所以会导致超时

#include<cstdio>

using namespace std;

void f(int,int);

int n,ans,k,a[1001]={1};

bool flag[1001]={true};

main()

{

scanf("%d%d",&n,&k);



f(n,1);

printf("%d",ans);

}

void f(int x,int y)

{

if (x==0&&y==k+1) {ans++;return;}

for (int i=a[y-1];i<=x;i++)

{

if (i<n)

{

x-=i;

a[y]=i;

f(x,y+1);

x+=i;

}

}

}

蒟蒻po主什么都不会,推导dp方程最后和标解一比发现错了(a[i][j]=a[i-1][j-1]+a[i-1][j]与a[i][j]=a[i-1][j-1]+a[i-j][j]),看来不细心认真,想敷衍了事是做不好什么东西的╮(╯▽╰)╭

#include<cstdio>

#include<iostream>

int a[2001][2001]={0};

using namespace std;

main()

{

int n,k;

//scanf("%ld%ld",&n,&k);

cin>>n>>k;

for (int i=1;i<=n;i++)

for (int j=1;j<=i;j++)

{

if (i==j) a[i][j]=1;

else if (j==1) a[i][j]=1;

else if (j>i) a[i][j]=0;//以上为几种特殊情况,其实有两条不加也并不影响什么

else a[i][j]=a[i-1][j-1]+a[i-j][j];//对于i,如果有1,我们要将它分成j份,那么我们可以取出一个1(有且仅有一个1作为单独的一份,然后i-1分成j-1份,即f1(i,j)=f(i-1,j-1);

//如果没有1,那么我们相当于把i-j分成j份,然后再给这j份分别加一个1,即f2(i,j)=f(i-j,j);

//最终得出f(i,j)=f1(i,j)+f2(i,j)=f(i-1,j-1)+f(i-j,j);

}

printf("%d",a
[k]);

}

还有一种很奇怪的用字符串的做法(pascal代码),好久以前写的不知道怎么的就过了,想了一下并总结也是类似于搜索的方法。

var s:string; ans:longint; pan:boolean;
procedure f(a:string);
var i,t,e:longint; b:string;
begin

 val(a,t,e);
 t:=t div 2;
  inc(ans);
 if t<>0 then
 begin
 for i:=1 to t do
 begin
   str(i,b);
   insert(b,a,1);
   f(b);
 end;
 end
 else exit;
end;
begin
 read(s);
 ans:=0;
 pan:=true;
 f(s);
 write(ans);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: