NOIP2003年普及组题解

这是第一题:https://www.luogu.org/problemnew/show/P1042
首先,在做题之前要注意两个地方:
‘E’不一定出现在文本的末尾,也不一定出现在某行的末尾
比赛必须要领先2个球才能获胜,11:10的比分是不存在的
好了,废话不多说,直接上代码~~~

#include
#include
#include
#include
#include
using namespace std;
const int maxN=100100;
string s[maxN];
int a[maxN],b[maxN],a2[maxN],b2[maxN];
int n=1,t=1,t2=1;

bool check(int x)
{
    int t=s[x].size();
    for(int i=0;iif(s[x][i]=='E')return 0;
    return 1;
}

int main()
{
    freopen("table.in","r",stdin);
    freopen("yable.out","w",stdout);
    cin>>s[n];
    while(check(n)){
        n++;
        cin>>s[n];
    }
    for(int i=1;i<=n;i++){
        int lenth=s[i].size();
        for(int j=0;jif(s[i][j]=='E'){
                for(int i=1;i<=t;i++)
                    cout<":"<cout<for(int i=1;i<=t2;i++)
                    cout<":"<return 0;
            }
            if(s[i][j]=='W')
                a[t]++,a2[t2]++;
            else if(s[i][j]=='L')
                b[t]++,b2[t2]++;
            if((a[t]>=11||b[t]>=11)&&abs(a[t]-b[t])>=2)
                t++;
            if((a2[t2]>=21||b2[t2]>=21)&&abs(a2[t2]-b2[t2])>=2)
                t2++;
            //这里一定要注意是领先两分才能赢
        }
    }
    return 0;
}

这里是第二题:https://www.luogu.org/problemnew/show/P1043
定义 f[0/1][i][j][k]表示左端点在 i,右端点在 j,分成了 k 个部分的最大/最小乘积
最开始做这题开了五层循环,内层枚举了一下断点和断点两侧分别分成了多少个部分…
后来(抄题解)发现了其实不用枚举两侧分成了多少个部分,因为这会被之前或之后的循环枚举到,打个比方:如果枚举到了左端点是 i,右端点是 j,断点是 k,左边分成了p 个部分,右边分成了 q 个部分。 当然,这里需要的是五重循环,这样做有超时的风险。
所以,我们只需要考虑最后一组数是从哪个地方开始的就好了
好了,道理讲完了,直接暴力上代码~~~

#include
#include
using namespace std;
const int maxN=0x7fffffff;
int n,m,maxn,minn=maxN;
int qzh[105];
int val[105];
int f[2][105][105][15];

int mod(int x){
    return (x%10+10)%10;
}

void prepare()
{
    for(int i=1;i<=(n<<1);i++)
        qzh[i]=qzh[i-1]+val[i];
    for(int i=1;i<=(n<<1);i++)
        for(int j=i;j<=(n<<1);j++)
            f[0][i][j][1]=f[1][i][j][1]=mod(qzh[j]-qzh[i-1]);
    for(int i=2;i<=m;i++){
        for(int l=1;l<=(n<<1);l++){
            for(int r=l+i-1;r<=l+n-1;r++){
                f[1][l][r][i]=maxN;
                for(int k=l+i-2;k0][l][r][i]=max(f[0][l][r][i],f[0][l][k][i-1]*mod(qzh[r]-qzh[k]));
                    f[1][l][r][i]=min(f[1][l][r][i],f[1][l][k][i-1]*mod(qzh[r]-qzh[k]));
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        maxn=max(maxn,f[0][i][i+n-1][m]);
        minn=min(minn,f[1][i][i+n-1][m]);
    }
}

int main()
{
    freopen("game.in","r",stdin);
    freopen("game.out","w"mstdout);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>val[i];
        val[i+n]=val[i];
    }
    prepare();
    cout<return 0;
}

P.S这道题有一点尴尬,就是我在做模拟赛的时候偷看了原来的程序,结果被老师看出来了。希望这是第一次,也是最后一次这种情况。(同学们千万不能像我这样,在考试的时候是不能翻看东西的,相反,考完试之后,要想尽一切方法去理解自己没有搞懂的题目,千万不要本末倒置。。。)

好了,言归正传,来到第三题:https://www.luogu.org/problemnew/show/P1044

说实话,这道题比第二题简单多了,就是一个普普通通的卡特兰数,对于卡特兰数,大家肯定都熟悉的不能再熟悉了,直接暴力上代码~~~

#include
#include 
using namespace std;
int n,f[20][20];

void prepare()
{
    for(int i=1;i<=n;++i){
        f[i][0]=1;
        for(int j=1;j<=i;++j){
            f[i][j]=f[i-1][j]+f[i][j-1];
        }
    }
}

int main()
{
    freopen("stack.in","r",stdin);
    freopen("stack.out","w",stdout);
    cin>>n;
    prepare();
    cout<

你可能感兴趣的:(C++,Junior,NOIP)