当前位置: 首页 > news >正文

刷题记录(NC231128 Steadily Growing Steam,NC21467 [NOIP2018]货币系统,NC235950 多重背包)

NC231128 Steadily Growing Steam

题目链接

关键点:

1、题目要求求在n张牌中,可以对齐中的k张牌的点数翻倍的条件下,分成点数相同的两堆,两队中取的价值总和最大

2、设dp[i][j][k]表示从前i张牌中,用j次技能(翻倍点数),两个集合点数相差k的情况下的最大价值,k的取值范围为(-2600,2600),有 负数,我们将其都加上2600,那么就为k(0,5200),因此所求的答案就为dp[n][k][2600];(k为使用技能的总次数)

3、转移情况总共有四种(以下采用了滚动数组):

1、将当前牌加入A集合,不使用技能,要判断k+t[i]<=5200(k为当前点数差,以下均为)

dp[i%2][j][k] = max(dp[i%2][j][k], dp[(i-1)%2][j][k+t[i]]+v[i]);

2、将当前牌加入B集合,不使用技能,要判断k-t[i]>=0

dp[i%2][j][k] = max(dp[i%2][j][k], dp[(i-1)%2][j][k-t[i]]+v[i]);

3、取当前牌,放入B集合,用技能,要判断k-t[i]*2>=0&&j(j不能为0)

dp[i%2][j][k] = max(dp[i%2][j][k], dp[(i-1)%2][j-1][k-2*t[i]]+v[i]);

4、取当前牌,放入A集合,用技能,要判断k+t[i]*2<=5200&&j

dp[i%2][j][k] = max(dp[i%2][j][k], dp[(i-1)%2][j-1][k+t[i]*2]+v[i]);

最后在这些中取最大值即可

完整代码:

# include <bits/stdc++.h>
using namespace std;
int n, k;
long long dp[2][110][5210];//前i个物品,用了j次技能,两个集合相差k的最大价值
int v[110], t[110];
int main()
{
    cin>>n>>k;
    for (int i=1; i<=n; i++)
    {
        cin>>v[i]>>t[i];
    }
    for (int i=0; i<=k; i++)
    {
        for (int j=0; j<=5200; j++)
            if (j!=2600)
            dp[0][i][j] = -1e18;
    }
    for (int i=1; i<=n; i++)
    {
        for (int j=0; j<=k; j++)
        {
            for (int k=0; k<=5200; k++)
            {
                dp[i%2][j][k] = dp[(i-1)%2][j][k];//不取当前牌
                if (k+t[i]<=5200)//取当前牌,放入A集合,不用技能
                    dp[i%2][j][k] = max(dp[i%2][j][k], dp[(i-1)%2][j][k+t[i]]+v[i]);
                if (k-t[i]>=0)//取当前牌,放入B集合,不用技能
                    dp[i%2][j][k] = max(dp[i%2][j][k], dp[(i-1)%2][j][k-t[i]]+v[i]);
                if (k-t[i]*2>=0&&j)//取当前牌,放入B集合,用技能
                    dp[i%2][j][k] = max(dp[i%2][j][k], dp[(i-1)%2][j-1][k-2*t[i]]+v[i]);
                if (k+t[i]*2<=5200&&j)//取当前牌,放入A集合,用技能
                    dp[i%2][j][k] = max(dp[i%2][j][k], dp[(i-1)%2][j-1][k+t[i]*2]+v[i]);
                    
            }
        }
    }
    cout<<dp[n%2][k][2600]<<endl;
    
    return 0;
}

NC21467 [NOIP2018]货币系统

题目链接

关键点:

1、本题要求求给出一个数列,求是否能使数组内的数可以互相表示,减少数组的数量,求这个最少的数量

2、用bool数组dp[i]表示i元是否能被表示,动态转移方程:dp[j] = dp[j] | dp [j-a[i]]; 因为一个货币可以使用多次,因此用一维数组,顺着遍历价值,就可以实现

3、如果一个币的价值,在开始用他组成价值前,已经被其他硬币表示,那么就可以去掉这个硬币

完整代码:

# include <bits/stdc++.h>
using namespace std;
int t, n;
int a[110];
bool dp[25000+10];
int main()
{
    cin>>t;
    while (t--)
    {
        cin>>n;
        int ans = n;
        for (int i=1; i<=n; i++)
            cin>>a[i];
        sort(a+1, a+1+n);
        memset(dp, 0, sizeof(dp));
        dp[0] = 1;
        for (int i=1; i<=n; i++)
        {
            if (dp[a[i]])
            {
                ans--;
                continue;
            }
            for (int j=a[i]; j<=a[n]; j++)
            {
                dp[j] = dp[j]|dp[j-a[i]]; 
            }
        }
        cout<<ans<<endl;
    }
    
    return 0;
}

NC235950 多重背包

题目链接

关键点:

1、一个物品有多件,将第i种物品分成若干见物品,其中每件物品有一个系数,这些物品的费用和价值均是原来的费用和价值乘以这个系数,使这些系数为

1,2,4,……2^(k-1),n[i]-2^k+1,且k是满足n[i]-2^k+1>0的最大整数,例如n[i]=13,则将这些物品分成1,2,4,6四件物品

完整代码:

# include <bits/stdc++.h>
using namespace std;
int n, t;
int x1, w1, v1, k, cnt;
int w[2010], v[2010];
int dp[2000+10];
int main()
{
    cin>>n>>t;
    for (int i=1; i<=n; i++)
    {
        cin>>x1>>w1>>v1;
        k = 1;
        while (k<=x1)
        {
            cnt++;
            w[cnt] = k*w1;
            v[cnt] = k*v1;
            x1-=k;
            k*=2;
        }
        if (x1>0)
        {
            cnt++;
            w[cnt] = x1*w1;
            v[cnt] = x1*v1;
        }
    }
    
    
    for (int i=1; i<=cnt; i++)
    {
        for (int k=t; k>=w[i]; k--)
        {
            dp[k] = max(dp[k], dp[k-w[i]]+v[i]);
        }
    }
    
    cout<<dp[t]<<endl;
    
    
    return 0;
}

相关文章:

  • 详解红黑树【C++实现】
  • Flask的一些简单代码
  • 链路追踪 - SkyWalking
  • 基于NFS共享存储实现KVM虚拟主机动态迁移
  • MySQL之常用存储引擎
  • 动手学习深度学习 02:预备知识
  • dockerkubernets篇(二十六)
  • 9.synchronized的三把锁
  • 为什么开发人员正在成为供应链攻击中的最薄弱环节
  • MySQL之事务、锁
  • 项目第二天
  • Windows与网络基础-10-windows用户管理
  • 计算机网络笔记(王道考研) 第三章:数据链路层
  • apifox 提取cookie字段添加自动鉴权
  • ATF启动(一):整体启动流程
  • [译]如何构建服务器端web组件,为何要构建?
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • C语言笔记(第一章:C语言编程)
  • java2019面试题北京
  • JS变量作用域
  • vue-cli在webpack的配置文件探究
  • VuePress 静态网站生成
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 聚类分析——Kmeans
  • 利用DataURL技术在网页上显示图片
  • 你真的知道 == 和 equals 的区别吗?
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 正则与JS中的正则
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • (1)(1.9) MSP (version 4.2)
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (Git) gitignore基础使用
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (一)appium-desktop定位元素原理
  • (一)认识微服务
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • (转) ns2/nam与nam实现相关的文件
  • (转)编辑寄语:因为爱心,所以美丽
  • (转)负载均衡,回话保持,cookie
  • .NET Core 2.1路线图
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .NET文档生成工具ADB使用图文教程
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • [120_移动开发Android]008_android开发之Pull操作xml文件
  • [20190416]完善shared latch测试脚本2.txt
  • [22]. 括号生成
  • [3300万人的聊天室] 作为产品的上游公司该如何?
  • [android] 看博客学习hashCode()和equals()