dp 20190618

C. Party Lemonade

这个题目是贪心,开始我以为是背包,不过也不太好背包,因为这个L都已经是1e9了。

这个题目怎么贪心呢?它是因为这里有一个二倍的关系,所以说val[i]=val[i-1]*2

所以利用这个关系,我们可以求出每一个体积的最小的花费。

这个处理完之后,我们就可以开始处理题目中的L了。

这个L,从高位开始枚举,先求出L个中最多并且要小于等于这个最大值可以用的这个物品的数量,然后如果是小于,那么再多选一次,这样肯定会超出体积,

不过这样就保证了大于等于L。

对于下面一个L取完膜之后继续这样处理,最后求出最小值。

#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iostream>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll val[50];

int main()
{
    int n;
    ll L;
    scanf("%d%I64d", &n, &L);
    for (int i = 1; i <= n; i++) scanf("%I64d", &val[i]);
    for (int i = 2; i <= n; i++) val[i] = min(val[i], val[i - 1] * 2);
    ll ans = inf64, sum = 0;
    for(int i=n;i>=1;i--)
    {
        ll len = 1 << (i - 1);
        ll num = L / len;
        sum += num * val[i];
        L %= len;
        ans = min(ans, sum + (L > 0)*val[i]);
    }
    printf("%I64d
", ans);
    return 0;
}
C

B. Dima and a Bad XOR

这个题目其实比较简单,就是找规律,如果找出来了,就很简单了。

首先我发现如果每一行有两个不同的数,那么肯定是可以的,然后lj发现如果最后一行有两个不相同的数,那么肯定也是可以的,最后就可以推出来

如果任意一行有两个数不同,那么肯定也是可以的。

这样子就很简单了。

#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iostream>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int mp[550][550];

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    int flag = 0, mark = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            scanf("%d", &mp[i][j]);
            if (!flag&&j > 1 && mp[i][j] != mp[i][1]) {
                flag = i;
                mark = j;
            }
        }
    }
    if (!flag)
    {
        int ans = 0;
        for (int i = 1; i <= n; i++) ans ^= mp[i][1];
        if (ans == 0) printf("NIE
");
        else
        {
            printf("TAK
");
            for (int i = 1; i < n; i++) printf("1 ");
            printf("1
");
        }
    }
    else
    {
        printf("TAK
");
        int ans = 0;
        for (int i = 1; i <= n; i++) ans ^= mp[i][1];
        if(ans)
        {
            for (int i = 1; i < n; i++) printf("1 ");
            printf("1
");
        }
        else
        {
            for(int i=1;i<=n;i++)
            {
                if (i == flag) printf("%d ", mark);
                else printf("1 ");
            }
            printf("
");
        }
    }
    return 0;
}
B

J 牛客假日团队赛1 分组

这个题目其实很不好想,这个是lj一步步引导我才写出来的,

首先这个题目每一个位置可以往后面推出 1~k 所以算一下复杂度是1e7

dp[i]表示以 i 为最后一个值,从 1~i 的最大的分完组之后的和。

所以这个就有刷表法和填表法,

就是从这个状态往后推和每一个状态从前面推过来,第一个很好写,后面那个比较难。

#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iostream>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 10;
int dp[maxn];
int a[maxn];
 
int main()
{
    int n, k;
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for(int i=0;i<=n;i++)
    {
        int mxx = 0;
        for(int j=1;j<=k;j++)
        {
            if (i + j > n) break;
            mxx = max(mxx, a[i + j]);
            dp[i + j] = max(dp[i + j], dp[i] + j * mxx);
            //printf("i=%d j=%d dp[%d]=%d
", i, j, i + j, dp[i + j]);
        }
    }
    printf("%d
", dp[n]);
    return 0;
}
1
#include <cstdio>
#include <cstring>
#include <queue>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iostream>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 10;
int dp[maxn];
int a[maxn];
 
int main()
{
    int n, k;
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for(int i=1;i<=n;i++)
    {
        int mxx = 0;
        for(int j=0;j<k;j++)
        {
            if (i < j + 1) break;
            mxx = max(mxx, a[i - j]);
            dp[i] = max(dp[i],dp[i - j - 1] + mxx * (j + 1));
            // printf("i=%d j=%d dp[%d]=%d dp[%d]=%d
", i, j, i, dp[i],i-j,dp[i-j]);
            // printf("mxx=%d
", mxx);
        }
    }
    printf("%d
", dp[n]);
    return 0;
}
2
原文地址:https://www.cnblogs.com/EchoZQN/p/11043552.html