[ACM] POJ1011 POJ2362解题报告, 状态压缩

10年9月17号Update…
状态压缩BFS 40行水过.. 代码是POJ2362的, 一样的题.. 原来本文只有1011

#include <stdio.h>

bool dfs(int a[],int u,int n,int __s,int start)
{
    if (start==n)
        return true;
    for(int i=(1<<start);i<(1<<n);i+=(2<<start)) {
        if(i&u)
            continue;
        int count=0;
        for(int j=0;j<n;j++)
            count+=a[j]*((i>>j)&1);
        if(count!=__s)
            continue;

        int __u=u|i;
        int j;
        for(j=0;j<n && ((__u>>j)&1);j++);
        if(dfs(a,__u,n,__s,j)) {
            /* DEBUG
            for(int k=0;k<n;k++)
                if((i>>k)&1)
                    printf("%d ",a[k]);
            printf("\n");   */
            return true;
        }
    }
    return false;
}


int main()
{
    int N;
    scanf("%d",&N);
    while (N--)
    {
        int n,a[21],count=0;
        scanf("%d",&n);
        for (int i=0;i<n;i++)
        {
            scanf("%d",a+i);
            count+=a[i];
        }
        printf("%s\n",count%4?"no":(dfs(a,0,n,count/4,0)?"yes":"no"));
    }
    return 0;
}


下面是一年前的垃圾代码.. 1011

#include <cstdio>
#include <cstdlib>

typedef struct part {
    int l,n;
    int who[65],used; ///How many does level[i] use; how many are used totally.
} Part;
Part a[65];
int l,n,m;  ///m records the amount of different lenths of sticks.
int myCompare(const void *a,const void *b) {
    return ((Part *)b)->l-((Part *)a)->l;
}

int next(int lv,int rem) {
    int i,j,r;
    while(1) {
        for(i=m;i>=1;i--)
            if(a[i].who[lv]>0)
                break;
        if(i==0)
            return -1;
        a[i].who[lv]--;
        a[i].used--;
        rem+=a[i].l;
        if(i==m)
            continue;
        for(j=i+1;j<=m;j++) {
            r=a[j].n-a[j].used;
            r=r<(rem/a[j].l)?r:rem/a[j].l;
            a[j].who[lv]+=r;
            a[j].used+=r;
            rem-=r*a[j].l;
        }
        return rem;
    }
}

bool vip_next(int lv1,int lv2,int s) {
    int rem=0;    ///lenths remained
    int i,r;
    bool lv1bigger=false;
    if(lv1!=lv2) {
        rem=l;
        for(i=0;i<=m;i++) {
            r=a[i].n-a[i].used;
            r=r<(rem/a[i].l)?r:rem/a[i].l;
            if(r<a[i].who[lv1])
                lv1bigger=true;
            else
                if(!lv1bigger)
                    r=a[i].who[lv1];
            a[i].used+=r;
            a[i].who[lv2]=r;
            rem-=r*a[i].l;
            if(!rem)
                break;
        }
    }
    else
        rem=next(lv2,rem);
    while(1) {
        if(a[s].who[lv2]==0) {
            for(i=s+1;i<=m;i++) {
                a[i].used-=a[i].who[lv2];
                a[i].who[lv2]=0;
            }
            return false;
        }
        if(rem==-1)
            return false;
        if(rem==0)
            return true;
        rem=next(lv2,rem);
    }
}

bool combine(int level) {
    int i,s;      ///s is which Part this level should start searching from
    if(level>n)
        return true;
    for(s=0;s<=m;s++)
        if(a[s].used!=a[s].n)
            break;
    for(i=0;i<=m;i++)
        if(a[i].used+a[i].who[level-1]>a[i].n) {
            if(!vip_next(level-1,level,s))
                return false;
            break;
        }
    if(i==m+1)
        for(i=0;i<=m;i++)
            a[i].used+=a[i].who[level]=a[i].who[level-1];
    while(1) {  ///At this point, this level's combination is ok.
        if(combine(level+1))
            return true;
        if(!vip_next(level,level,s))
            return false;
    }
}

int main() {
    int i,j,temp,count;
    while(1) {
        m=0;
        for(i=0;i<65;i++)
            a[i].used=a[i].n=0;
        scanf("%d",&n);
        if(!n)
            return 0;
        count=0;
        for(i=1;i<=n;i++) {
            scanf("%d",&temp);
            for(j=1;j<=m;j++)
                if(a[j].l==temp) {
                    a[j].n++;
                    break;
                }
            if(j>m) {
                m++;
                a[m].l=temp;
                a[m].n++;
            }
            count+=temp;
        }
        ///Initialize
        qsort(a+1,m,sizeof(Part),myCompare);
        a[0].n=1;
        a[0].who[0]=1;
        a[0].used=1;

        for(l=a[1].l;l<=count;l++) {
            n=count/l;
            a[0].l=l;
            for(i=1;i<=m;i++) {
                a[i].used=0;
                for(j=1;j<=n;j++)
                    a[i].who[j]=0;
            }
            if(count%l)
                continue;
            if(combine(1)) {
                printf("%d\n",l);
                break;
            }
        }
        /*
        for(j=1;j<=5;j++) {
            printf("\nlevel %d use ",j);
            for(i=1;i<=m;i++) {
                    printf(" %d (*%d)\n",a[i].l,a[i].who[j]);
            }
        }*/
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *