UVALive 3667 dfs

题目的数据量一看就是暴力的解法,直接深搜模拟一下题目的过程就可以了,具体做法可以看看下面的代码。由于忘记把初始输入的数据排序WA了好多次。查错的时候发现一组数据:
9 3 6 10 12 14 16 19 24 26
正确答案应该是
6
0 14 24 26 30 33
而网上的一些AC代码的结果都是
7
0 3 6 10 22 24 26
问题在于题目中的两个约束条件:刻度尽量少和尺子长度尽量短之间的优先级关系,题目里没有明确说清楚。有些代码剪枝时认为“如果超过最大的尺度那么这个解就是不合格的”。但是根据题目意思,应该是M先要保证最小,然后再是ans[M-1]尽量小。不过题目数据比较水,两种都能ac通过。
再提供几个测试数据:
4 1 3 7 11
11 1 2 3 4 5 6 7 8 9 10 11
0
Case 1:
4
0 1 4 11
Case 2:
6
0 1 2 3 7 11

#include<stdio.h>
#include<string.h>
#include<algorithm>
int s[55],depth,vis[55],N,z[10];//z[]表示选中的数
bool sel[1000010];
bool dfs(int bz,int x){
//  printf("   - dfs(%d,%d)\n",bz,x);
    if(x==depth){
    //  printf(" -> ");
    //  for(int i=0;i<x;i++)printf("%d ",z[i]);
    //  printf("%d\n",s[N]);
        for(int i=1;i<N;i++)if(!vis[i]){
            bool flag=false;
            for(int j=0;j<x;j++){
                if(sel[z[j]+s[i]]){
                flag=true;break;};
            }
            if(!flag){
    //          printf("<= %d([%d])\n",s[i],i);
                return false;
            }
        }
        return true;
    }else{
        for(int i=bz;i<N;i++)if(!vis[i]){
            int t;
            for(int j=0;j<x;j++)if(!sel[t=z[j]+s[i]]){
            vis[i]=1;
            z[x]=t;
            sel[t]=1;
            if(dfs(i+1,x+1))return true;
            sel[t]=0;
            vis[i]=0;
            }
        }
    }
    return false;
}
int main(){
    int cas=1;
//  freopen("1.in","r",stdin);
//  freopen("1.txt","w",stdout);
    while(~scanf("%d",&N),N){
        for(int i=1;i<=N;i++) scanf("%d",s+i);
        std::sort(s+1,s+N+1);
        sel[s[N]]=1;
        for(depth=1;depth<=6;depth++){
            if(dfs(1,1)){
                z[depth]=s[N];
                std::sort(z+1,z+depth+1);
                printf("Case %d:\n%d\n0",cas++,depth+1);
                for(int i=1;i<=depth;i++)printf(" %d",z[i]);
                printf("\n",s[N]);
                break;
            }
        }
        memset(vis,0,sizeof(vis));
        memset(sel,0,sizeof(sel));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值