NOIP模拟题 [构造][贪心][暴力]

8 篇文章 0 订阅
3 篇文章 0 订阅

从以往犯的错上汲取经验。
注意循环,if的嵌套以及break等地方。
训练暴力能力。
如果要修改一个地方一定注意看一下有没有忘了的东西!还有复制黏贴也是一样。

T1:
题意:
给定一些字符串,可对字符串的长度为偶数的前缀进行反转操作,相同则消除,求最后剩下多少。
分析:
先考虑把后面的匹配,则只要把某两个看作一块,只要还有一个相同且没有被配对的块,就一定可以被翻到最前面且调换方向,然后翻到最后。
没有break导致多次配对,以后一定要有满足就返回的思想。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<ctime>
#define ll long long 
#define inf 2e8
#define modd 1e9+7
#define clr(x) memset(x,0,sizeof(x))
#define maxen(x) memset(x,127,sizeof(x))
#define maxer(x) memset(x,31,sizeof(x))
#define minus(x) memset(x,-1,sizeof(x))
#define each(i,n,m) for(int i=n;i<m;i++)
#define eachrev(i,n,m) for(int i=n;i>m;i--)
#define minn(a,b,c) min(a,min(b,c))
#define maxx(a,b,c) max(a,max(b,c))
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define PROC "kahuucino"
//for(int i=1;i<=n;i++)
//(double) (ll) LL (int)
//(double)clock()/CLOCKS_PER_SEC
using namespace std;
const int Maxn=55;
int ans,t,n,len[Maxn],used[Maxn],bj[Maxn];
char a[Maxn][Maxn];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void init()
{
    n=read();
    each(i,1,n+1){
        cin.getline(a[i],Maxn);
        len[i]=strlen(a[i]);
    }
    ans=0;clr(used);
}
void work()
{
    each(i,1,n+1)
        if(!used[i])
        each(j,1,n+1)
            if(!used[j]&&i!=j){
                if(len[i]!=len[j])continue;
                if(len[i]%2&&a[i][len[i]-1]!=a[j][len[i]-1])continue;
                clr(bj);
                for(int k=0;k<len[i];k+=2){
                    for(int z=0;z<len[i];z+=2)
                        if((!bj[z])&&a[i][k]==a[j][z]&&a[i][k+1]==a[j][z+1]){
                            bj[z]=1;break;}
                        else if((!bj[z])&&a[i][k]==a[j][z+1]&&a[i][k+1]==a[j][z]){
                            bj[z]=1;break;}
                }
                int flg=0;
                    for(int z=0;z<len[i];z+=2)
                        if(!bj[z]){
                            flg=1;break;
                        }
                    if(!flg){
                        used[i]=used[j]=1;
                        break;
                }
            }
    for(int i=1;i<=n;i++)
        if(!used[i])ans++;
    printf("%d\n",ans);
}
void debug()
{
    //
}
int main()
{
    freopen(PROC".in","r",stdin);
    freopen(PROC".out","w",stdout);
    t=read();
    each(i,0,t){
    init();
    work();
    }
    //debug();
    return 0;
}

T2:
题意:
给定一些怪物的参数,要求选出一怪物和与之战斗的怪物,使得最后这一怪物的能量+能力值最大。
对战斗定义如下:
只有能力严格更大才能赢,赢后能力加上战败者能量,减去战败者能力。
分析:
把怪物分为能力大和能力小于等于,然后去取两类的最优比较即可。
最优定义:
能力小于等于:能力排序。
证明:先不考虑自身能力能量和打败对方,则能力更大的可能获取到的至少不会更小。
然后考虑自身能力,考虑能力小的怪物能打败能力大的怪物的情况,另一情况显然更满足。
令a2 < <script type="math/tex" id="MathJax-Element-4"><</script>b2,a1< b1,a2>a1;(a:能力,b能量,下同)
则能力大的怪物此模块的值:a2+b2+b1-a1;
小的:a1+b1+b2-a2;
作差得:2a2-2a1>0;
得证。
能力大:能力+能量排序。
证明:
令a1+b1>a2+b2;
a1< a3< a2;
b3>a3;
人话来说就是考虑有一个排序更高的不能杀死一个排序低的能杀死且收益为正的怪物。
a3+b3>a1+b1+b3-a3;
若a2杀死a3,收益:
a2+b2+b3-a3;
若a3不死,自身:
a3+b3;
所以对于能力大的怪物,要么就直接不杀,如果要杀,则被杀的那个不被杀反而是最优,所以只用考虑不杀的情况,得证。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<ctime>
#define ll long long 
#define inf 2e8
#define modd 1e9+7
#define clr(x) memset(x,0,sizeof(x))
#define maxen(x) memset(x,127,sizeof(x))
#define maxer(x) memset(x,31,sizeof(x))
#define minus(x) memset(x,-1,sizeof(x))
#define each(i,n,m) for(int i=n;i<m;i++)
#define eachrev(i,n,m) for(int i=n;i>m;i--)
#define minn(a,b,c) min(a,min(b,c))
#define maxx(a,b,c) max(a,max(b,c))
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define PROC "zyougamaya"
//for(int i=1;i<=n;i++)
//(double) (ll) LL (int)
//(double)clock()/CLOCKS_PER_SEC
using namespace std;
const int Maxn=1e5+5;
struct node
{
    long long figh,ener;
    int num;
}kuri[Maxn];
int bigg[Maxn],smal[Maxn]; 
int bigghead,smalhead;
long long n,biggtot,smaltot,figh,ener,fighbigg,fighsmal,enerbigg,enersmal;
long long read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
bool cmp1(int x,int y)
{
    return kuri[x].figh+kuri[x].ener>kuri[y].figh+kuri[y].ener;
}
bool cmp2(int x,int y)
{
    if(kuri[x].figh!=kuri[y].figh)return kuri[x].figh>kuri[y].figh;
    return kuri[x].ener>kuri[y].ener;
}
bool cmp3(node x,node y)
{
    return x.figh<y.figh;
}
void init()
{
    n=read();
    each(i,1,n+1){
        kuri[i].figh=read();
        kuri[i].ener=read();
        kuri[i].num=i;
        if(kuri[i].figh>kuri[i].ener)
            bigg[++bigghead]=i;
        else smal[++smalhead]=i;
    }
    sort(bigg+1,bigg+bigghead+1,cmp1);
    fighbigg=kuri[bigg[1]].figh;
    enerbigg=kuri[bigg[1]].ener;
    sort(smal+1,smal+smalhead+1,cmp2);
    fighsmal=kuri[smal[1]].figh;
    enersmal=kuri[smal[1]].ener;
    sort(kuri+1,kuri+n+1,cmp3);
}
void work()
{
    if(bigghead){
        figh=fighbigg;
        ener=enerbigg;
        for(int i=1;i<=n;i++){
            if(figh<=kuri[i].figh)break;
            if(kuri[i].num==bigg[1])continue;
            if(kuri[i].figh>=kuri[i].ener)continue;
            figh+=kuri[i].ener-kuri[i].figh;
        }
        biggtot=figh+ener;
    }
    if(smalhead){
        figh=fighsmal;
        ener=enersmal;
        for(int i=1;i<=n;i++){
            if(figh<=kuri[i].figh)break;
            if(kuri[i].num==smal[1])continue;
            if(kuri[i].figh>=kuri[i].ener)continue;
            figh+=kuri[i].ener-kuri[i].figh;
        }
        smaltot=figh+ener;
    }
    printf("%I64d",max(biggtot,smaltot));
}
void work2()
{
    for(int i=1;i<=n;i++){
        figh=kuri[i].figh;
        ener=kuri[i].ener;
        for(int j=1;j<=n;j++){
            if(figh<=kuri[j].figh)break;
            if(i==j)continue;
            if(kuri[j].figh>=kuri[j].ener)continue;
            figh+=kuri[j].ener-kuri[j].figh;
        }
        biggtot=max(biggtot,figh+ener);
    }
    printf("%I64d",max(biggtot,smaltot));
}
void debug()
{
    //
}
int main()
{
    freopen(PROC".in","r",stdin);
    freopen(PROC".out","w",stdout);
    init();
    if(n>=1000)work();
    else work2();
    //debug();
    return 0;
}

T3:
题意:
模拟文件处理系统,支持文件夹,文件的进入创建删除列表,支持进入父目录。
分析:
就一暴力,双向存树,儿子节点用邻接链表,一个数组表示是否被删(因为直接在链表上删不方便),按照时间顺序列表的时候就递归打印。
如果要修改一个地方一定注意看一下有没有忘了的东西!还有复制黏贴也是一样。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<ctime>
#define ll long long 
#define inf 2e8
#define modd 1e9+7
#define clr(x) memset(x,0,sizeof(x))
#define maxen(x) memset(x,127,sizeof(x))
#define maxer(x) memset(x,31,sizeof(x))
#define minus(x) memset(x,-1,sizeof(x))
#define each(i,n,m) for(int i=n;i<m;i++)
#define eachrev(i,n,m) for(int i=n;i>m;i--)
#define minn(a,b,c) min(a,min(b,c))
#define maxx(a,b,c) max(a,max(b,c))
#ifdef WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif
#define PROC "nacumegu"
//for(int i=1;i<=n;i++)
//(double) (ll) LL (int)
//(double)clock()/CLOCKS_PER_SEC
const int Maxn=105;
int n,len,cur=1,cnt=1;
int typ[Maxn],exi[Maxn],fa[Maxn],fr[Maxn],tov[Maxn];
using namespace std;
string opt,name[Maxn];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void init()
{
   n=read();
   exi[cur]=typ[cur]=1;
}
void cdD()
{
    string a="";
    for(int i=3;i<len;i++)
        a+=opt[i];
    for(int i=fr[cur];i;i=tov[i])
        if(exi[i]&&typ[i]&&name[i]==a){
            cur=i;return;
        }
    printf("No such directory!\n");
}
void cdf()
{
    if(fa[cur]){
        cur=fa[cur];return;
    }
    printf("No parent directory!\n");
}
void tou()
{
    string a="";
    for(int i=6;i<len;i++)
        a+=opt[i];
    for(int i=fr[cur];i;i=tov[i])
        if(exi[i]&&typ[i]==0&&name[i]==a){
            printf("File already exists!\n");
            return;
        }
    tov[++cnt]=fr[cur];
    fr[cur]=cnt;
    exi[cnt]=1;
    name[cnt]=a;
    fa[cnt]=cur;
}
void rmf()
{
    string a="";
    for(int i=3;i<len;i++)
        a+=opt[i];
    for(int i=fr[cur];i;i=tov[i])
        if(exi[i]&&typ[i]==0&&name[i]==a){
            exi[i]=0;
            return;
        }
    printf("No such file!\n");
}
void rmd()
{
    string a="";
    for(int i=6;i<len;i++)
        a+=opt[i];
    for(int i=fr[cur];i;i=tov[i])
        if(exi[i]&&typ[i]&&name[i]==a){
            exi[i]=0;
            return;
        }
    printf("No such directory!\n");
}
void mkd()
{
    string a="";
    for(int i=6;i<len;i++)
        a+=opt[i];
    for(int i=fr[cur];i;i=tov[i])
        if(exi[i]&&typ[i]&&name[i]==a){
            printf("Directory already exists!\n");
            return;
        }
    tov[++cnt]=fr[cur];
    fr[cur]=cnt;
    exi[cnt]=1;
    typ[cnt]=1;
    name[cnt]=a;
    fa[cnt]=cur;
}
void ls(int pr)
{
    if(!pr)return;
    ls(tov[pr]);
    if(exi[pr])cout<<name[pr];
    if(exi[pr])printf(" <%c>\n",(typ[pr]?'D':'F'));
}
void work()
{
    each(i,0,n){
        getline(cin,opt);
        len=opt.size();
        if(opt[0]=='c'&&opt[3]=='.')
            cdf();
        else if(opt[0]=='c')
            cdD();
        else if(opt[0]=='t')
            tou();
        else if(opt[0]=='r'&&opt[2]=='d')
            rmd();
        else if(opt[0]=='r')
            rmf();
        else if(opt[0]=='m')
            mkd();
        else ls(fr[cur]);
    }
}
void debug()
{
    //
}
int main()
{
    freopen(PROC".in","r",stdin);
    freopen(PROC".out","w",stdout);
    init();
    work();
    //debug();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值