SDUT 3099 递归回溯?

题目描述

X压着YY压着Z,那么YZ都是位于在X的下面的巧克力。若YX下面,ZY下面,那么Z也是位于在X的下面的巧克力


多组输入。

首先输入一个n1 <= n <= 1000),代表有n块巧克力。

对于每组输入,输出个整数代表答案,两个数之间用空格隔开。

示例输入

5
1 1 2
2 0
3 2 4 5
4 0
5 0

示例输出

1 0 2 0 0

提示

来源

zmx

示例程序



一开始以为是二叉树

然后还没开始敲被晓楠找出了一个反例

讨论他觉得可以按层建立节点

我给他找了个反例


在这里有了分歧,他说7是1下面的巧克力

我觉得不是

这时候果断@出题人员(也就是啸爷

然后他被驳回了

这时候我大概有思路了

这特喵的就是递归撒

于是有了以下的代码

#include<cstdio>
using namespace std;

int arr[1005][5];
int ans[2][1005];

int f(int n){
    if(ans[0][n]!=-1)
        return ans[0][n]+1;
    ans[0][n]=0;
    for(int i=0;i<ans[1][n];i++)
        ans[0][n]+=f(arr[n][i]-1);
    return ans[0][n]+1;
}

int main(){
    int n;
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++)
            ans[0][i]=-1;
        int s;
        for(int i=0;i<n;i++){
            scanf("%d",&s);
            s--;
            scanf("%d",&ans[1][s]);
            for(int j=0;j<ans[1][s];j++)
                scanf("%d",&arr[s][j]);
        }
        for(int i=0;i<n;i++)
            f(i);
        for(int i=0;i<n-1;i++)
            printf("%d ",ans[0][i]);
        printf("%d\n",ans[0][n-1]);
    }
    return 0;
}

然后嘛,就是喜闻乐见的WA

然后上群里求助~

被找出了一组错误数据

6
1 2 2 3
2 1 4
3 1 4
4 2 5 6
5 0
6 0

(不同分支相同子节点我重复计算了

然后感觉原来的思路不行,要推到重来


#include<cstdio>
using namespace std;

const int MAX=1005;

int child[MAX][3];
int chnum[MAX];

bool ans[MAX][MAX];
bool check[MAX];

int n;

void loop(int num){
    if(check[num]==false){
        check[num]=true;
        for(int i=0;i<chnum[num];i++){
            loop(child[num][i]-1);
            ans[num][child[num][i]-1]=true;
            for(int j=0;j<n;j++)
                ans[num][j]=ans[num][j] || ans[child[num][i]-1][j];
        }
    }
    return;
}

int main(){
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++){
            check[i]=false;
            for(int j=0;j<n;j++)
                ans[i][j]=false;
        }
        int s;
        for(int i=0;i<n;i++){
            scanf("%d",&s);
            s--;
            scanf("%d",&chnum[s]);
            for(int j=0;j<chnum[s];j++)
                scanf("%d",&child[s][j]);
        }
        for(int i=0;i<n;i++){
            loop(i);
            int an=0;
            for(int j=0;j<n;j++)
                if(ans[i][j])
                    an++;
            if(i!=n-1)
                printf("%d ",an);
            else
                printf("%d\n",an);
        }
    }
    return 0;
}

刚开始没有这么多数组的。。。但是后来写的越来越乱

干脆都拆开了

1Y

(以上

-------------------------------------奇怪の分割线-------------------------

使用了bitset作为优化

跑的比香港记者还快!

#include<cstdio>  
#include<cstring>  
#include<algorithm>  
#include<bitset>  
#include<vector>  
using namespace std;  
  
const int maxn=1010;  
bitset<maxn> cola[maxn];  
vector<int> edge[maxn];  
bool vis[maxn];  
  
void init(){  
    for(int i=0;i<maxn;i++){  
        cola[i].reset();  
        cola[i].set(i);  
    }  
    for(int i=0;i<maxn;i++)  
        edge[i].clear();  
    memset(vis,0,sizeof(vis));  
}  
  
void dfs(int st){  
    vis[st]=true;  
    for(vector<int>::iterator it=edge[st].begin();it!=edge[st].end();it++){  
        if(vis[*it]==false)  
            dfs(*it);  
        cola[st] = cola[st] | cola[*it] ;  
    }  
}  
  
int main(){  
    int n;  
    while(~scanf("%d",&n)){  
        init();  
        int x,y;  
        for(int i=1;i<=n;i++){  
            scanf("%d %d",&x,&y);  
            int p;  
            for(int j=0;j<y;j++){  
                scanf("%d",&p);  
                edge[x].push_back(p);  
            }  
        }  
        for(int i=1;i<=n;i++){  
            if(vis[i]==false)  
                dfs(i);  
        }  
        for(int i=1;i<=n;i++)  
            printf(i<n?"%d ":"%d\n",cola[i].count()-1);  
    }  
    return 0;  
}  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值