QBXT2018 4 29 DP&图论班 胡策 by zhx

PS:由于长者是以我们没有学过图论与DP的基础上出的题,所以可能(?)会有点水。

题意:

T1:判断括号序列是是否合法。可以利用栈,别忘了判断最终栈是否为空。

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

char s[1000],z[1000];

int size;

int main()
{
    scanf("%s",s+1);
    int l=strlen(s+1);
    size++;
    z[size]=s[1];
    for (int a=2;a<=l;a++)
    {
        if (s[a]==')')
        {
            if (z[size]!='(')
            {
                printf("Wrong\n");
                return 0;
            }
            else size--;
        }
        if (s[a]==']')
        {
            if (z[size]!='[')
            {
                printf("Wrong\n");
                return 0;
            }
            else size--;
        }
        if (s[a]=='}')
        {
            if (z[size]!='{')
            {
                printf("Wrong\n");
                return 0;
            }
            else size--;
        }
        if (s[a]=='(' || s[a]=='[' || s[a]=='{')
        {
            size++;
            z[size]=s[a];
        }
    }
    if (size!=0) printf("Wrong\n");
    else printf("OK\n");

    return 0;
}
a-std by zhx

T2:0/1/2背包 可以将物品复制一份跑0/1背包板子,也可以变化转移方程

f[i][j]=max{f[i-1][j],f[i-1][j-w[i]]+v[i],f[i-1][j-2*w[i]]+2*v[i]}

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=210;

int n,m,w[maxn],v[maxn],f[maxn][maxn];

int main()
{
    scanf("%d%d",&n,&m);
    for (int a=1;a<=n;a++)
        scanf("%d%d",&w[a],&v[a]);
    for (int a=0;a<n;a++)
        for (int b=0;b<=m;b++)
        {
            f[a+1][b]=max(f[a+1][b],f[a][b]);
            if (b+w[a+1]<=m) f[a+1][b+w[a+1]]=max(f[a+1][b+w[a+1]],f[a][b]+v[a+1]);
            if (b+2*w[a+1]<=m) f[a+1][b+2*w[a+1]]=max(f[a+1][b+2*w[a+1]],f[a][b]+2*v[a+1]);
        }
    int ans=0;
    for (int a=0;a<=m;a++)
       ans=max(ans,f[n][a]);
    printf("%d\n",ans);
    return 0;
}
b-std by zhx

T3:超神贪心

 钟长者说:”这道题放在第二题下面,就是让你们把它当成背包做的。“。。。然后全场只有一位同学拿了10分,不愧为防AK好题 PS:好像这题一星期前还是最长上升子序列。。

此题具有特殊性质:每件物品都是1x2或1x3的,因此我们所选的物品就像俄罗斯方块一样放在一起。

SO此题可以抽象为选a个1x2的物品,b个1x3的物品。而我们可以贪心地将物品按价值从大到小拿取。

这里我们可以前缀和优化,预处理出前i件物品的价值和。其中s2[]代表1x2的价值前缀和,s3[]代表1x3的价值前缀和。

①枚举a,b 则答案ans为max{ans,s2[a]+s3[b]};

②可以只枚举b 然后根据b算出a

贪心地想,我们需要将剩余的空间尽可能用1x2的方格填满,因此所选择的1x2的方格的数量为a=min{n1,a=(n*m-3*b)/2}//n1为已知的1x2方格的数量 ,’/‘为整除(下取整)

证明:当我们填完枚举的1x3的方格时,会留下两个矩形。↓

 

当矩形1宽度为0时,a的数目取决于矩形2面积的奇偶性 即a=(n*m-3*b)/2

当矩形1宽度为1时,我们可以先用2格方格填充矩形2 而矩形2最多会被留出一个1x1个空间 然后再竖着用2格方格填满矩形1 因此a的数目也为(n*m-3*b)/2

当矩形1宽度为2时,我们可以用2格方格填满矩形1 而a的数目取决于矩形2面积的奇偶性 即a=(n*m-3*b)/2

③那么b的范围是什么呢?是min(n2,n*m/3) 吗?//n2为已知的1x3方格的数量

有特殊情况:当空间为1x2、2x1、2x2时,不能放1x3的方格,因此这些情况应当特判。

有同学可能会问,若矩形2形成了2x2的方格会有影响吗?比如5x5

我们可以这么摆

也可以这么摆

因此只需特判2x2、1x2、2x1的情况即可。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=10010;

int n,m,n1,n2,y[maxn],z[maxn],sum[maxn];

bool cmp(int a,int b)
{
    return a>b;
}

int main()
{
    int t;
    scanf("%d",&t);
    for (;t--;)
    {
        scanf("%d%d%d%d",&n,&m,&n1,&n2);
        for (int a=1;a<=n1;a++)
            scanf("%d",&y[a]);
        for (int a=1;a<=n2;a++)
            scanf("%d",&z[a]);
        sort(y+1,y+n1+1,cmp);
        sort(z+1,z+n2+1,cmp);
        for (int a=1;a<=n1;a++)
            y[a]+=y[a-1];
        for (int a=1;a<=n2;a++)
            z[a]+=z[a-1];
        int delta;
        if (n%3==2 && m%3==2 && (n==2 || m==2)) delta=4;
        else delta=n*m%3;
        int ans=0,limit=min(n2,(n*m-delta)/3);
        for (int a=0;a<=limit;a++)
            ans=max(ans,z[a]+y[min(n1,(n*m-a*3)>>1)]);
        printf("%d\n",ans);
    }

    return 0;
}
c-std by zhx

T4:

考场上想出了正解,然而又想了个数据,是”不是最短路上的一条边连着一个速度很大的马“。然后就写了个BFS,拿了40。。。。

已知有Q次询问,每次询问从u到v的最短时间,再根据数据范围,可以判断此题需要用到Floyd。

易证相同速度时路程越短时间越少,因此可以先预处理出任意两点间的最短路。

然后判断有哪些最短路是可以不换马走完的,此时该路径的时间即为“路径长度/路径起点的马的速度“。

根据这些已经得到的时间,我们可以进一步得到需要换马的路所需的时间,从而得到任意两点间的最短时间。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=110;

int n,q,e[maxn],s[maxn];

double dis[maxn][maxn],dist[maxn][maxn];

int main()
{
    int T=1;
    for (int t=1;t<=T;t++)
    {
        scanf("%d%d",&n,&q);
        for (int a=1;a<=n;a++)
            scanf("%d%d",&e[a],&s[a]);
        for (int a=1;a<=n;a++)
            for (int b=1;b<=n;b++)
            {
                scanf("%lf",&dis[a][b]);
                if (dis[a][b]<0) dis[a][b]=1e+20;
                if (a==b) dis[a][b]=0;
            }
        for (int a=1;a<=n;a++)
            for (int b=1;b<=n;b++)
                for (int c=1;c<=n;c++)
                    dis[b][c]=min(dis[b][c],dis[b][a]+dis[a][c]);
        for (int a=1;a<=n;a++)
            for (int b=1;b<=n;b++)
                dist[a][b]=1e+20;
        for (int a=1;a<=n;a++)
            dist[a][a]=0;
        for (int a=1;a<=n;a++)
            for (int b=1;b<=n;b++)
                if (dis[a][b]<=e[a]) dist[a][b]=dis[a][b]/s[a];
        for (int a=1;a<=n;a++)
            for (int b=1;b<=n;b++)
                for (int c=1;c<=n;c++)
                    dist[b][c]=min(dist[b][c],dist[b][a]+dist[a][c]);
        //printf("Case #%d:",t);
        for (int a=1;a<=q;a++)
        {
            int s,e;
            scanf("%d%d",&s,&e);
            printf("%.6lf\n",dist[s][e]);
        }
    }

    return 0;
}
d-std by zhx

猜你喜欢

转载自www.cnblogs.com/Loi-Brilliant/p/8972124.html
今日推荐