2021 Shanghai I,K

I - Steadily Growing Steam

Gym 103446I

题目大意

\(n\)张牌,每张牌有价值\(v_i\)和点数\(t_i\),现在你能最多使\(k\)张牌的点数乘\(2\),然后从中取出若干张牌,分成两组,使得两组的点数和相同,问最大的价值是多少。\((1\leq n\leq100,0\leq k\leq n,|v_i|\leq10^9,1\leq t_i\leq13)\)

思路

首先可以想到背包,我们定义\(dp[i][t1][t2][k]\)为取到第\(i\)张牌时,左边的牌堆点数和为\(t1\),右边牌堆的点数和为\(t2\),且亦有\(k\)张牌的点数被乘\(2\)了的情况的最大价值,然后发现这样的数组是开不下的,所以我们可以去掉一维,就变成了\(dp[i][t1-t2][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\times n\)的时间之内,这条链会变回原来的样子。\((2\leq n\leq123)\)

思路

有一个统一的构造方法,当长度为\(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;
}
posted @ 2022-03-30 15:04  Jerry_Black  阅读(76)  评论(0)    收藏  举报