2021 Shanghai I,K

I - Steadily Growing Steam

Gym 103446I

题目大意

n张牌,每张牌有价值vi和点数ti,现在你能最多使k张牌的点数乘2,然后从中取出若干张牌,分成两组,使得两组的点数和相同,问最大的价值是多少。(1n100,0kn,|vi|109,1ti13)

思路

首先可以想到背包,我们定义dp[i][t1][t2][k]为取到第i张牌时,左边的牌堆点数和为t1,右边牌堆的点数和为t2,且亦有k张牌的点数被乘2了的情况的最大价值,然后发现这样的数组是开不下的,所以我们可以去掉一维,就变成了dp[i][t1t2][k],这样就刚好能开下,不过前面的i也可以用滚动数组滚掉,然后就轻松AC了。

代码

#include<bits/stdc++.h>
using namespace std;
long long val[105];
int t[105];
long long dp[105][5205][105];
long long ans=0;
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld%d",&val[i],&t[i]);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=5200;j++)
        {
            for(int l=0;l<=k;l++)
            {
                if(dp[i-1][j][l])
                {
                    dp[i][j+t[i]][l]=max(dp[i][j+t[i]][l],dp[i-1][j][l]+val[i]);
                    dp[i][j-t[i]][l]=max(dp[i][j-t[i]][l],dp[i-1][j][l]+val[i]);
                    if(l<k)dp[i][j+2*t[i]][l+1]=max(dp[i][j+2*t[i]][l+1],dp[i-1][j][l]+val[i]);
                    if(l<k)dp[i][j-2*t[i]][l+1]=max(dp[i][j-2*t[i]][l+1],dp[i-1][j][l]+val[i]);
                    dp[i][j][l]=max(dp[i][j][l],dp[i-1][j][l]);
                }
            }
        }
        dp[i][2600+t[i]][0]=max(val[i],dp[i][2600+t[i]][0]);
        dp[i][2600-t[i]][0]=max(val[i],dp[i][2600-t[i]][0]);
        dp[i][2600+2*t[i]][1]=max(val[i],dp[i][2600+2*t[i]][1]);
        dp[i][2600-2*t[i]][1]=max(val[i],dp[i][2600-2*t[i]][1]);
    }
    for(int i=0;i<=k;i++)ans=max(ans,dp[n][2600][i]);
    printf("%lld\n",ans);
    return 0;
}
/*
4 1
10 1
-5 3
5 1
6 1
*/

K - Circle of Life

Gym - 103446K

题目大意

有一条n个点的链,每个点最多只能放1,每秒钟每个1都会消失且它的左边和右边都会出现一个1,两个1相撞后就会消逝,问能否构造出一种初始的放法使得在2×n的时间之内,这条链会变回原来的样子。(2n123)

思路

有一个统一的构造方法,当长度为4的时候,1001,当长度为5的时候,10001,在最后加上10也是不影响的,所以除了3之外的所有数都是可以被这样构造出来的,然后3是没有办法构造的,所以这道题就做完了。

代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    scanf("%d",&n);
    int a=0,b=0,c=0;
    if(n==3)printf("Unlucky\n");
    else
    {
        if(n&1){b++;n-=5;}
        a=n/4;
        c=(n%4==2);
        for(int i=1;i<=a;i++)printf("1001");
        for(int i=1;i<=b;i++)printf("10001");
        for(int i=1;i<=c;i++)printf("10");
        printf("\n");
    }
    return 0;
}

__EOF__

本文作者Jerry-Black
本文链接https://www.cnblogs.com/Jerry-Black/p/16077162.html
关于博主:小蒟蒻一只( ̄^ ̄)ゞ
版权声明:转载请注明来源哟~ QAQ
声援博主:UP UP UP !!!
posted @   Jerry_Black  阅读(59)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示