中山普及Day13——普及

又是迷之自信的说。。。估的230,考的50整,我欲上天呐!!!


T1:深渊(怕不是黑暗种族聚集地???)

思路:动归。而且是简单动归。转移方程:Fi,j=max(Fi-1,j,Fi,j,Fi-1,(j-modi+m)%m)其中i表示第i个,j表示此时的余数。

最后答案即为Fi,0

见代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,v[5001],mod[5001],dp[5001][5001];
int main()
{
    freopen("abyss.in","r",stdin);
    freopen("abyss.out","w",stdout);
    memset(dp,-0x3f3f3f,sizeof(dp));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&v[i]);
        mod[i]=v[i]%m;
    }
    dp[0][0]=0;
    for(int i=1;i<=n;i++)
        for(int j=0;j<m;j++)
        {
            dp[i][j]=max(dp[i-1][j],dp[i][j]);
            dp[i][j]=max(dp[i][j],dp[i-1][(j-mod[i]+m)%m]+v[i]);
        }
    printf("%d",dp[n][0]);
    return 0;
}

好题哉!!!


T2:fight

有一只触手怪,有好多好多触手。(莫不是从诡秘之主里跑出来的)

类似这种:

每条触手上有n条绳子,那是勇士为了杀死他完成工会任务套上的。但是触手怪有一些灵智,所以每两根触手只能绑一根。现给你一种绑法,看是否可行。

思路:贪心,每次从大到小排序,把最大的向下绑好。最后看会不会多出来就可以了。

见代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int t,n,a[801];
bool flag;
bool cmp(int x,int y)
{
    return x>y;
}
int main()
{
    freopen("fight.in","r",stdin);
    freopen("fight.out","w",stdout);
    scanf("%d",&t);
    for(int k=1;k<=t;k++)
    {
        flag=false;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        sort(a+1,a+1+n,cmp);
        for(int i=1;i<=n;i++)
        {
            int k=0;
            for(int j=1;i+j<=n;j++)
            {
                if(a[i+j]>0)
                {
                    a[i+j]--;
                    k++;
                }
                if(k==a[i])
                {
                    break;
                }
            }
            if(k!=a[i])
            {
                flag=true;
                break;
            }
            sort(a+1,a+1+n,cmp);
        }
        if(flag==true)
        printf("NO\n");
        else
        printf("YES\n");
    }
    return 0;
}

好题哉!!!


T3:游戏机

 

思路:拿一个前向星存个图,然后储蓄一下左上到右下,左下到右上的路径长度,即为0或1,因为不可能再走一遍,会诞生环。

然后安心跑最短路,迪杰就可以了,可怜我不会前向星,全部爆空间。

见代码;

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,flag=1,g[20001][20001],dij[20001];
bool book[20001];
char c;
void dijs()
{
    dij[1]=0;
    book[1]=true;
    while(flag!=n*m)
    {
        int minIndex=0x3f3f3f3f,minnum=1;
        for(int i=2;i<=n*m;i++)
        {
            if(!book[i])
            {
                if(minIndex>dij[i])
                {
                    minIndex=dij[i];
                    minnum=i;
                }
            }
        }
        book[minnum]=true;
        flag++;
        for(int i=2;i<=n*m;i++)
        {
            if(!book[i]&&g[minnum][i]!=0x3f3f3f)
            {
                if(g[minnum][i]+dij[minnum]<dij[i])
                dij[i]=g[minnum][i]+dij[minnum];
            }
        }
    }
}
int main()
{
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    memset(g,0x3f3f3f,sizeof(g));
    memset(dij,0x3f3f3f,sizeof(dij));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    g[i][i]=0;
    for(int i=1;i<n;i++)
        for(int j=1;j<m;j++)
        {
            scanf(" %c",&c);
            if(int(c)==92)
            {
                g[(i-1)*m+j+1][i*m+j]=1;g[i*m+j][(i-1)*m+j+1]=1;
                g[(i-1)*m+j][i*m+j+1]=0;g[i*m+j+1][(i-1)*m+j]=0;
                if(((i-1)*m+j+1)==2&&(i*m+j)==(i*m+1))
                {
                    dij[m+2]=0;
                }

            }
            else
            {
                g[(i-1)*m+j][i*m+j+1]=1;g[i*m+j+1][(i-1)*m+j]=1;
                g[(i-1)*m+j+1][i*m+j]=0;g[i*m+j][(i-1)*m+j+1]=0;
                if((i-1)*m+j==1&&i*m+j+1==i*m+2)
                {
                    dij[m+2]=1;
                }
            }
        }
    dijs();
    printf("%d",dij[n*m]);
    return 0;
}

好题哉!!!


T4:拓扑排序

如题,再嵌一个中位数。这个非常复杂,这里不讲。

好题哉!!!

 

posted @ 2019-08-13 21:34  青殇  阅读(185)  评论(3编辑  收藏  举报