CF #190(DIV2)总结

首先说说做CF的感受把:大多数是智力题,而且偏向某个方向很严重,而且答案具有开放性,可以有多种解。所以这轮的主题也就是“贪心”。

A. Ciel and Dancing
   这题题目建模,给定一张二部图,左边N各节点,右边M个节点,要求一种连接法连接左右两部,使的所有边的点都有一个是只有一条边的。

   那么贪心思想,首先让n1与所有m结合,然后在用m2与所有n(除了n1之外)相连就行了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        if(n <= m){
            printf("%d\n",n+m-1);
            for(int i=1;i<=m;i++)
                printf("1 %d\n",i);
            for(int i=2;i<=n;i++)
                printf("%d 1\n",i);
        }else{
            printf("%d\n",n+m-1);
            for(int i=1;i<=n;i++)
                printf("%d 1\n",i);
            for(int i=2;i<=m;i++)
                printf("1 %d\n",i);
        }
    }
    return 0;
}                                                                                                
B. Ciel and Flowers

题意:有三种方法构成花束,三朵红或者绿或者蓝,还有各种颜色各一朵,先给出三种花朵的数目,求能组成的最多的花束。

贪心:比较几种构成法,求其中那个最多的那种。(想不到我也有今天,对不起勒,题解太简略了,赶时间啊)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

int main()
{
    int r,g,b;
    while(~scanf("%d%d%d",&r,&g,&b)){
        int sum123 = r/3 + g/3 + b/3 + min(r%3,min(g%3,b%3));
        int sum12 = r/3 + g/3 + min(r%3,min(g%3,b)) + (b-min(r%3,min(g%3,b)))/3;
        int sum23 = g/3 + b/3 + min(g%3,min(b%3,r)) + (r-min(g%3,min(b%3,r)))/3;
        int sum13 = r/3 + b/3 + min(r%3,min(b%3,g)) + (g-min(r%3,min(b%3,g)))/3;
        int sum1 = r/3 + min(r%3,min(b,g))+(b-min(r%3,min(b,g)))/3+(g-min(r%3,min(b,g)))/3;
        int sum2 = g/3 + min(g%3,min(r,b))+(r-min(g%3,min(r,b)))/3+(b-min(g%3,min(r,b)))/3;
        int sum3 = b/3 + min(b%3,min(r,g))+(r-min(b%3,min(r,g)))/3+(g-min(b%3,min(r,g)))/3;
        int sum = min(r,min(g,b))+(r-min(r,min(g,b)))/3+(g-min(r,min(g,b)))/3+(b-min(r,min(g,b)))/3;
        int ans;
        ans = max(sum1,sum2);
        ans = max(ans,sum3);
        ans = max(ans,sum12);
        ans = max(ans,sum13);
        ans = max(ans,sum23);
        ans = max(ans,sum123);
        ans = max(ans,sum);
        cout<<ans<<endl;
    }
}

C. Ciel and Robot

题意:给定一个走法序列,只能重复该序列,不能改变顺序,问该走法序列能否帮助机器人走到目标点(a,b )。

首先求出一次走法序列能向右走多少,向上走多少,判断该位移能否满足目标点,如不行,然后枚举走法序列每一步的位移,看看该位移是否满足被目标点整除的情况(大概是这个意思,赶时间啊)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 106

char str[maxn];

int main()
{
    int a,b;
    while(~scanf("%d%d",&a,&b)){
        getchar();
        gets(str);
        int len = strlen(str);
        int flag = 0;
        int x = 0,y = 0;

        for(int i=0;i<len&&flag==0;i++){
            if(x==a && y==b) flag = 1;
            if(str[i]=='U') y++;
            if(str[i]=='D') y--;
            if(str[i]=='L') x--;
            if(str[i]=='R') x++;
            if(x==a && y==b) flag = 1;
        }
        if(flag == 0){
            int q=0,p=0;
            for(int i=0;i<len&&flag==0;i++){
                if(str[i]=='U') q++;
                if(str[i]=='D') q--;
                if(str[i]=='L') p--;
                if(str[i]=='R') p++;

                if(x==0 && y==0){
                    if(p==a && q==b) flag = 1;
                }else if(x==0 && y!=0){
                    if(p==a && (b-q)%y==0 && (b-q)/y>=0)
                        flag = 1;
                }else if(y==0 && x!=0){
                    if(q==b && (a-p)%x==0 && (a-p)/x>=0)
                        flag = 1;
                }else{
                    if((a-p)%x==0&&(b-q)%y==0&&(b-q)/y==(a-p)/x&&(a-p)/x>=0)
                        flag = 1;
                }
            }
        }
        if(flag) puts("Yes");
        else puts("No");
    }
    return 0;
}

D. Ciel and Duel

题意:游戏王玩过吧,给定你的攻击怪兽的攻击力,给出对手的攻击性怪兽的攻击力、防守型怪兽的防守力,还可以直接对玩家进行伤害,计算能造成的最多伤害。

首先,将我方怪兽攻击力高低排序,对方怪兽防守力、攻击力分别排序

贪心策略:(1)考虑对玩家进行直接伤害,即用我方怪兽消灭对方所有怪兽,剩余怪兽直接伤害,按照这种理论,我们就需要首先把所有的防守型怪兽消灭,而且是利用最小大过其防守力的怪兽去ATK,然后,如果还有怪兽,就用大过对方攻击型怪兽的最小的攻击力的怪兽消灭对方攻击性怪,最后剩下的怪兽直接攻击。

(2)不考虑直接伤害,那么用最大攻击力的怪去打对方攻击性攻击力最小的怪,如此做,即可。

最后比较两种方法的好坏即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 106

int n,m;
int top1,top2;
int a[maxn];
bool hash[maxn];
int b1[maxn]; //进攻
int b2[maxn]; //防守

int f1(){
    int x1=0,x2=0;
    int ret = 0;
    memset(hash,false,sizeof(hash));
    for(int i=0;i<m&&x2<top2;i++) {
        if(hash[i]==false && a[i]>b2[x2]){
            hash[i] = true;
            x2++;
        }
    }
    for(int i=0;i<m&&x1<top1;i++){ //这里一定是用攻击力小的击败对手atk型怪兽,然后用高攻击的怪直接攻击
        if(hash[i]==false && a[i]>=b1[x1]){
            ret += a[i] - b1[x1];
            x1++;
            hash[i] = true;
        }
    }
    if(x2==top2 && x1==top1){
        for(int i=0;i<m;i++){
            if(hash[i]==false) ret += a[i];
        }
    }
    return ret;
}

int f2(){
    int x1 = 0,x2=0;
    int ret = 0;
    memset(hash,false,sizeof(hash));
    for(int i=m-1;i>=0 && x1<top1;i--){
        if(hash[i]==false&&a[i]>=b1[x1]){
            ret += a[i] - b1[x1];
            x1++;
            hash[i]=true;
        }
    }
    for(int i=0;i<m&&x2<top2;i++){
        if(hash[i]==false&&a[i]>b2[x2]){
            hash[i] = true;
            x2++;
        }
    }
    if(x1==top1 && x2==top2){
        for(int i=0;i<m;i++){
            if(hash[i]==false) ret += a[i];
        }
    }
    return ret;
}

int main()
{
    while(~scanf("%d%d",&n,&m)){
        getchar();
        char cmd[5];
        int ss;
        top1 = 0,top2 = 0;
        for(int i=0;i<n;i++){
            scanf("%s%d",cmd,&ss);
            if(cmd[0]=='A') b1[top1++] = ss; //进攻
            else b2[top2++] = ss; //防守
        }
        for(int i=0;i<m;i++){
            scanf("%d",&a[i]);
        }
        sort(a,a+m);
        sort(b1,b1+top1);
        sort(b2,b2+top2);
        int sum1 = f1();
        int sum2 = f2();
        int ans = max(sum1,sum2);
        cout<<ans<<endl;
    }
    return 0;
}

E. Ciel the Commander

题意:给定一棵树,要求标级别(A~Z,A最小),相邻两个点级别不能相同,相同级别的两个点之间必有比他们级别大的点,求一种标级方案。

这是最有价值的一道题目,利用自底向上的算法,假设我们已经表记好了子树根节点T1,T2,T3.....TK,如何标记他们的根节点,首先只要有两个子根节点级别相同,则根节点必须大于之,不能出现与子根节点的级别相同的级别。

这里关键技术又变为如何dfs这个树并标记了,有用到了强大的二进制了,只有26个字母么,11111代表用了A~E……,懂了吧。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxm 300006
#define maxn 100005

typedef struct {
    int to,next;
}Edge;
Edge e[maxm];
int head[maxn];
int n;
int e_cnt;
struct Tree{
    int stu; //二进制表示使用了哪一种等级,如10代表使用了B等级
    int rank; //等级
}tree[maxm];
bool flag;

void init(){
    memset(head,-1,sizeof(head));
    e_cnt = 0;
}

void add(int u,int v){
    e[e_cnt].to = v;
    e[e_cnt].next = head[u];
    head[u] = e_cnt;
    e_cnt++;
}

void dfs(int x,int fa){
    int stu = 0;
    int dub = 0; //度数
    for(int i=head[x];i!=-1;i=e[i].next){
        int v = e[i].to;
        if(v == fa) continue;
        dfs(v,x);
        dub = max(dub,stu&tree[v].stu);
        stu |= tree[v].stu;
    }
    int &p = tree[x].stu;
    p = 1;
    while(p<=dub || (p&stu)) p <<= 1;
    for(int i=(p<<1);i<(1<<26);i<<=1) if(i&stu) p |= i;
    for(int i=0;i<26;i++){
        if((1<<i)&tree[x].stu){
            tree[x].rank = 26 - i - 1;
            if(tree[x].rank<0 || tree[x].rank>26) flag = true;
            return ;
        }
    }
}

int main()
{
    while(~scanf("%d",&n)){
        memset(tree,0,sizeof(tree));
        init();
        flag = false;
        int u,v;
        for(int i=0;i<n-1;i++){
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1,0);
        if(flag ) cout<<"Impossible!";
        else{
            for(int i=1;i<=n;i++) cout<<char(tree[i].rank+'A')<<" ";
        }
        cout<<endl;
    }
    return 0;
}




 

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值