noip online 入门组

文具订购

枚举每种情况,比较找出最优的那种就可以了。

时间复杂度好像有点高,应该是擦着边过的。(我以为过不了,结果学校oj给过了)

#include<bits/stdc++.h>
using namespace std;
int ans,ans2=-1;
int a,b,c;
int cmp(int a,int b,int c)
{
    if(a>=c&&b>=c) return c;
    if(b<=a&&b<=c) return b;
    else return a;
}
int main()
{
    int n;
    scanf("%d",&n); 
    if(n==0) 
    {
        printf("0 0 0");
        return 0;
    } 
    else 
    {
        for(int i=0;i<=n/7;i++) 
        {
            for(int j=0;j<=n/4;j++)
            {
                int k=n-7*i-4*j;
                if(k%3==0&&k>=0)
                {
                    k/=3;
                    int s=cmp(i,j,k);
                    if(ans<s)
                    {
                        ans=s;
                        ans2=i+j+k;
                        a=i;b=j;c=k;
                    }
                    else if(ans==s)
                    {
                        if(ans2<i+j+k)
                        {
                            ans2=i+j+k;
                            a=i;b=j;c=k;
                        }
                    }
                }
            }
        }
    }
    if(ans2!=-1) printf("%d %d %d",a,b,c);
    else cout<<-1;
    return 0;
}

跑步

一开始就很明显直接用背包就能做。

相当于的一个二维dp,状态转移方程:f[i][j]=f[i-1][j-1]+f[i-j][j]。

但是会超时,只能拿70分。

所以在这个二维的基础上利用乘法原理再优化。

分成两种情况:

小于根号n,此时可以把上面的二维dp化成一维:f[j]=f[j]+f[j-i]。

大于等于根号n时,状态转移方程为:f[i][j]=f[i][j-i],f[i-1][j-m]。

最后,两种情况相乘合并就可以了。

70分代码:

#include<bits/stdc++.h>
using namespace std;
int n,MOD,ans;
int f[5005][5005];
int main() 
{
    scanf("%d%d",&n,&MOD);
    for(int i=1;i<=n;i++) 
    f[i][1]=1;
    for(int i=2;i<=n;i++) 
    {
        for(int j=2;j<=i;j++) 
        {
            f[i][j]=(f[i-1][j-1]+f[i-j][j])%MOD;
        }
    }
    for(int i=1;i<=n;i++) 
    ans+=f[n][i],ans%=MOD;
    printf("%d\n",ans);
    return 0;
}

100分代码:

#include<bits/stdc++.h> 
long long d[100002],f[1002][100002];
int main()
{
    int n,MOD;
    scanf("%d%d",&n,&MOD);
    int m=sqrt(n)+1;
    d[0]=f[0][0]=1;
    for(int i=1;i<m;i++)
    {
        for(int j=i;j<=n;j++)
        {
            d[j]=(d[j]+d[j-i])%MOD;
        }
    }
    for(int i=1;i<m;i++)
    {
        for(int j=i;j<=n;j++)
        {
            f[i][j]=f[i][j-i];
            if(j>=m) f[i][j]=(f[i][j]+f[i-1][j-m])%MOD;
        }
    }
    long long ans=0;
    for(int i=0;i<=n;i++)
    {
        long long x=0;
        for(int j=0;j<m;j++)
        {
            x=(x+f[j][n-i])%MOD;
        }
        ans+=x*d[i];
        ans%=MOD;
    }
    printf("%d",ans);
    return 0;
}

魔法

因为有6个点都是k=0的特殊情况,此时就是一个纯的最短路算法。

用Floyd骗了30分。

#include<bits/stdc++.h>
using namespace std;
long long f[102][102];
int main() 
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=100;i++) 
    {
        for(int j=1;j<=100;j++)
        {
            f[i][j]=10000000000;
        }
    }
    for(int i=1;i<=m;i++) 
    {
        int t,u,v;
        scanf("%d%d%d",&u,&v,&t);
        f[u][v]=t;
    }
    for(int k2=1;k2<=n;k2++) 
    {
        for(int i=1;i<=n;i++) 
        {
            for(int j=1;j<=n;j++) 
            f[i][j]=min(f[i][j],f[i][k2]+f[k2][j]);
        }
    }
    printf("%lld\n",f[1][n]);
    return 0;
}

正解等我来填坑吧。

posted @ 2020-03-14 17:41  mgtnb  阅读(374)  评论(0编辑  收藏  举报