POJ 3628 - Bookshelf 2

DFS

 

 

题意大致为:就是说FJ,有个栏杆,然后栏杆有个高度H,现在FJ有N个奶牛,每个奶牛有个高度hi,现在将奶牛堆起来(这里不知道怎么翻译了),使得堆起来的高度大于等于H,现在要求最小高度差。

 

之前我一直在想用dp来做,提交了也一直WA,错误代码如下:

#include <stdio.h>
#include <string.h>
int main()
{
    int i,j;
    int n,b,h[25],sum,dp[20000005];
    while(scanf("%d%d",&n,&b));
    {
        sum=0;
        for(i=0; i<n; i++)
        {
            scanf("%d",&h[i]);
            sum+=h[i];
        }
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(i=0; i<n; i++)
            for(j=sum; j>=h[i]; --j)
                {
                    if(dp[j-h[i]])
                        dp[j]=1;
                }
        for(i=b; i<=sum; i++)
            {
                if(dp[i])
                {
                    printf("%d\n",i-b);
                    break;
                }
            }
    }
    return 0;
}


后来,在网上看见许多人都用  DFS 来写,于是就AC了。

 

在我的DFS代码中,我做了几点优化:

1.首先是搜索顺序,从大到小排列利于直接跳出。

2.当  当前高度 + 最小高度 - H >= min(目前最小高度)时,跳出。

3.由于是要求最小高度差min,所以当min等于0的时候,直接跳出。


AC代码如下:

#include <stdio.h>
#define M 1000005
int N,H;
int h[M],min,sum = 0;
void init()
{
    int i,j,tmp;
    scanf("%d%d",&N,&H);
    for (i=0;i < N; i++)
    {
        scanf("%d",&h[i]);
        sum+=h[i];
    }
    for (i=0;i < N-1;i++)
        for (j=i+1;j<N;j++)
        if (h[i]<h[j])
        {
            tmp = h[i];
            h[i] = h[j];
            h[j] = tmp;
        }
    min = sum-H;
}
void DFS(int depth , int sum)
{
    if (!min) return;
    if (sum >= H)
    {
        if(sum - H < min)
            min = sum - H;
    }
    if (depth == N) return ;
    if (sum + h[N-1] - H >= min) return ;
    DFS(depth + 1,sum + h[depth]);
    DFS(depth + 1,sum);
}

int main()
{
    init();
    DFS(0,0);
    printf("%d\n",min);
    return 0;
}



你可能感兴趣的:(POJ 3628 - Bookshelf 2)