2004年普及组总结

20 篇文章 0 订阅
12 篇文章 0 订阅

这是第一题:https://www.luogu.org/problemnew/show/P1085
这道题,没有什么好说的吧,就是暴力枚举就好了

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int a,b,s,max=0,i,day=0;//a和b是津津每天上课的时间,s是上课时间之和 

int main ()
{
    freopen("unhappy.in","r",stdin);
    freopen("unhappy.out","w",stdout); 
    for(i=1;i<8;i++){
        cin>>a>>b;
        s=a+b;
        if ((s>max)&&(s>8)){
            max=s;
            day=i;
        }//在超过8小时且比之前几天都大的s时,将s赋给最大值,并记录下JJ的这天
    }
    cout<<day<<endl;//由于刚开始day的初值就是0,如果每一天都开心的话,直接输出就好了 
    return 0;             
}

这是第二题:https://www.luogu.org/problemnew/show/P1086
这道题,刚开始的时候,题目理解错了,本意应该是“一直找最大的,直到没有时间为止”,但是我却理解成为了“在单位时间里面所能获得的最大价值”,这就很尴尬了。。。
言归正传,这道题其实模拟就好了啊

#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<utility>
#include<cmath>
#include<cstdio>
using namespace std;
int m,n,k=1,t,u,ans;
struct peanuts{
    int x,y,time,w;
}p[1000001];//(x,y)为坐标,time为时间,w表示数量 
int a[1010][1010];

void qsort(int l,int r)
{
    if(l>=r)
        return;
    int t=p[rand()%(r-l+1)+l].w;
    int i=l,j=r;
    while(i<=j){
        while(p[i].w>t)i++;
        while(p[j].w<t)j--;
        if(i<=j){
            swap(p[i],p[j]);
            i++;
            j--;
        }
    }
    qsort(l,j);
    qsort(i,r);
}

int main()
{
    cin>>m>>n>>t;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            cin>>a[i][j];
            if(a[i][j]>0){//当有花生的时候。。。 
                p[k].w=a[i][j];
                p[k].x=i;
                p[k].y=j;
                k++;
            }
        }
    }
    srand(100000000);
    qsort(1,k);
    for(int i=1;i<=k;i++){
        u=p[i].x;
        //由于我们要考虑多多采花生返回,而返回的路程就是深度即x,如果加上这个x可以按时返回的话就采这个花生。
        if(i==1)
            p[i].time=p[i].x+1;
            //第一个花生是不同的,因为多多一开始可以跳到第一个最多花生的所在列
        else  
            p[i].time=p[i-1].time+abs(p[i].x-p[i-1].x)+abs(p[i].y-p[i-1].y)+1;
        //不是第一个的话就加上与前一个的坐标差再加采摘时间
        if(p[i].time+u<=t)
            ans+=p[i].w;
        //如果数据合法那么就把花生数加上就好了 
    }
    cout<<ans<<endl;
    return 0;
}

这里是第三题:https://www.luogu.org/problemnew/show/P1087
这道题,大概可以分为三步:
1.建树。按照题意是在递归过程中建立树,建树的方法实际上就是树的先序遍历(先根节点,再左右子树)。当本节点长度大于1时递归建立子树。
2.输出。而输出过程是对树的后序遍历(先左右子树,再根节点),这里有个技巧就是可以和建树过程集成在一起。只需将代码放在递归调用之后就可以了。
3.判断。最后是判断当前节点的FBI树类型,可以用B(初始值为1)保存全是‘0’的情况,如果遇到‘1’就将B置为0,用I(初始值为1)保存全是‘1’的情况,如果遇到‘0’就将I置为0。最后判断B和I中的值,如果两个都为0则输出F(不全为‘0’,不全为‘1’)。

讲完步骤,我们来讲一点实现方面的东西,我们可以用前缀和来存储一的个数(在这个数里面的值不是一,就是零,所以数值是多少,就代表有多少个一)。
最后,附上代码~~~

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
int n,s[2000];
string a;

void prepare()
{
    s[0]=a[0]-'0';
    for(int i=1;i<(1<<n);++i)
        s[i]=s[i-1]+a[i]-'0';//维护一个前缀和 
}

void maketree(int l,int r)
{
    if(l<r){
        maketree(l,(l+r)/2); 
        maketree((l+r+1)/2,r);
    }
    int k=s[r]-s[l-1];//统计从l到r这个区间里面有多少个一 
    if(k==0)//全部都是零的时候才会是'B' 
        cout<<"B";
    else if(k==(r-l+1))//全部都是一的时候才会是'I' 
        cout<<"I";
    else//剩余情况都是'F' 
        cout<<"F";
}

int main()
{
    cin>>n>>a;
    prepare();
    maketree(0,(1<<n)-1);
    cout<<endl;
    return 0;
}

终于到了第四题了,题目在这里:https://www.luogu.org/problemnew/show/P1088
这道题嘛,直觉告诉我模拟一下深度优先搜索,就是说第一次搜索的时候直接到达外星人给出的那个结点,然后再慢慢往回推。等到求到的全排列是外星人给出的加上我们要加的数字时,就大功告成了!!!
最后附上代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
const int maxn=10010;
int n,m,a[maxn],flag,flagx;
bool s[maxn];

void dfs(int step)
{
    if(flagx==1)
        return;
    if(step>n){
        flag++;
        if(flag==m+1){
            //现在到了我们要加上的那个数的全排列的时候
            //我们就直接地输出,然后标记flagx,一直return,结束程序
            for(int j=1;j<=n;j++)
                cout<<a[j]<<" ";
            cout<<endl;
            flagx=1;
        }
        return;
    }
    for(int i=1;i<=n;i++){
        if(flag==0)
            i=a[step];
            //当还在外星人给出的排列这个阶段的时候,我们就直指外星人给出的序列中的数
        if(s[i]==0){
            s[i]=1;
            a[step]=i;
            dfs(step+1);
            s[i]=0;
        }
    }
}

int main()
{
    freopen("martian.in","r",stdin);
    freopen("martian.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    dfs(1);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值