1月20日学习总结

解题思路:分别建立两个数组,一个存储每个物品的价值和价钱,另一个存储捆绑后和价值和价钱,将捆绑的物品的价值和价钱全部累加在其根的价值和价钱上,然后对捆绑后的价值和价钱做01背包问题处理

题目描述

明天就是母亲节了,电脑组的小朋友们在忙碌的课业之余挖空心思想着该送什么礼物来表达自己的心意呢?听说在某个网站上有卖云朵的,小朋友们决定一同前往去看看这种神奇的商品,这个店里有 nn 朵云,云朵已经被老板编号为 1,2,3,...,n1,2,3,...,n,并且每朵云都有一个价值,但是商店的老板是个很奇怪的人,他会告诉你一些云朵要搭配起来买才卖,也就是说买一朵云则与这朵云有搭配的云都要买,电脑组的你觉得这礼物实在是太新奇了,但是你的钱是有限的,所以你肯定是想用现有的钱买到尽量多价值的云。

输入格式

第一行输入三个整数,n,m,wn,m,w,表示有 nn 朵云,mm 个搭配和你现有的钱的数目。

第二行至 n+1n+1 行,每行有两个整数, c_i,d_ici​,di​,表示第 ii 朵云的价钱和价值。

第 n+2n+2 至 n+1+mn+1+m 行 ,每行有两个整数 u_i,v_iui​,vi​。表示买第 u_iui​ 朵云就必须买第 v_ivi​ 朵云,同理,如果买第 v_ivi​ 朵就必须买第 u_iui​ 朵。

输出格式

一行,表示可以获得的最大价值。

输入输出样例

输入 #1复制

5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2

输出 #1复制

1

说明/提示

  • 对于 30\%30% 的数据,满足 1 \le n \le 1001≤n≤100;
  • 对于 50\%50% 的数据,满足 1 \le n,w \le 10^31≤n,w≤103,1 \le m \le 1001≤m≤100;
  • 对于 100\%100% 的数据,满足 1 \le n \le 10^41≤n≤104,0 \le m \le 5 \times 1
    #include<iostream>
    using namespace std;
    int pre[100],dp[100],w[100],c[100],s[100]={0},x[100]={0},q;//w单个价格,c单个价值,s捆绑价格,x捆绑价值
    int fd(int x)
    {
        if(pre[x]==x)
            return x;
        else
        {
            pre[x]=fd(pre[x]);
            return pre[x];
        }
    }
    void un(int x,int y)
    {
        pre[fd(x)]=fd(y);
    }
    int main()
    {
        int n,m,k,t;//n朵云,m种搭配
        cin>>n>>m>>q;
        int l=m;
        for(int i=1;i<=n;i++){
            cin>>w[i]>>c[i];
            pre[i]=i;//将其根指向自己
        }
        for(int i=1;i<=m;i++)
        {
            cin>>k>>t;
            un(k,t);
        }
        for(int i=1;i<=n;i++)//确保每个有关系的物品的根是同一个
        {
            while(m>=0){
            pre[i]=pre[pre[i]];
            m--;}
            m=l;
        }
        //cout<<pre[1]<<' '<<pre[2]<<' '<<pre[3]<<' '<<pre[4]<<' '<<pre[5]<<endl;
        for(int i=1;i<=n;i++)
        {
            s[pre[i]]+=w[i];
            x[pre[i]]+=c[i];//将价值和价钱累加在根上
        }
    
        //for(int i=1;i<=n;i++)
        //{
        //    cout<<s[i]<<' '<<x[i]<<' ';
        //}
        //cout<<endl;
        for(int i=1;i<=n;i++)
            for(int j=q;j>=s[i];j--){
               dp[j]=max(dp[j],dp[j-s[i]]+x[i]);//拿和不拿,比较价值
               //cout<<dp[j]<<' ';
            }
        cout<<dp[q];
    }
    
    

 

 

题目描述

给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,长度\le 8≤8)。

输入格式

22行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。

输出格式

11行,表示一棵二叉树的先序。

输入输出样例

输入 #1复制

BADC
BDCA

输出 #1复制

ABCD

说明/提示

【题目来源】

NOIP 2001 普及组第三题

#include<iostream>
#include<cstring>
using namespace std;

string a,b;
void line(int z,int zx,int h,int hx)
{
    int m;
    if(z==zx)//停止条件
        return ;
    //else
    //cout<<z<<zx<<h<<hx<<endl;
    for(int i=0; i<zx; i++)
    {
        if(a[i]==b[hx-1])//根节点位置
        {
            m=i;
            cout<<a[i];
            break;
        }
    }
    line(z,m,h,h-z+m);//左子树
    line(m+1,zx,h-z+m,hx-1);//右子树
    return ;
}
int main()
{
    cin>>a;
    cin>>b;
    line(0,a.length(),0,b.length());//字符串长度
}

不知道为什么不能用gets输入字符串

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值