[COCI2016-2017#3] Kroničan 解题记录

news/2024/5/19 21:28:08 标签: c++, 算法, 推荐算法, 动态规划

[COCI2016-2017#3] Kroničan 解题记录


题意简述

N N N 个装有水的杯子,你需要通过从一个杯子向另一个杯子倒水,使这些杯子里面至多有 K K K 个有水,从杯子 i i i 往杯子 j j j 倒水的代价是 C i , j C_{i,j} Ci,j


题目分析

数据范围: 1 ≤ N ≤ 20 1 \leq N \leq 20 1N20,一眼状压。
d p S dp_S dpS 表示当前装有水的杯子集合为 S S S,每次枚举从杯子 k ∈ [ 1 , n ] k \in [1,n] k[1,n] 向杯子 j ∈ [ 1 , n ] j \in [1,n] j[1,n]倒水。因为一开始所有杯子都有水,越到后面水越少,所以考虑倒序转移,即从 2 n − 1 2^n-1 2n1 1 1 1 转移。
状态转移方程:
d p S ⨁ j ← min ⁡ k = 1 n d p S + C j , k dp_{S \bigoplus {j}} \gets \min \limits _{k=1}^{n}dp_{S}+C_{j,k} dpSjk=1minndpS+Cj,k
对于最后统计答案,我们可以用 __builtin_popcount() 函数(我这里是手写的),对于二进制中 1 1 1 的个数小于等于 K K K 的更新。


AC Code
#include<bits/stdc++.h>
#define arrout(a,n) rep(i,1,n)std::cout<<a[i]<<" "
#define arrin(a,n) rep(i,1,n)std::cin>>a[i]
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define dep(i,x,n) for(int i=x;i>=n;i--)
#define erg(i,x) for(int i=head[x];i;i=e[i].nex)
#define dbg(x) std::cout<<#x<<":"<<x<<" "
#define mem(a,x) memset(a,x,sizeof a)
#define all(x) x.begin(),x.end()
#define arrall(a,n) a+1,a+1+n
#define PII std::pair<int,int>
#define m_p std::make_pair
#define u_b upper_bound
#define l_b lower_bound
#define p_b push_back
#define CD const double
#define CI const int
#define int long long
#define il inline
#define ss second
#define ff first
#define itn int
CI N=25;
int n,K,ans=LLONG_MAX,c[N][N],dp[(1<<N-5)+5];
int calc(int x){
    int cnt=0;
    rep(i,0,20){
        if((x>>i)&1){
            cnt++;
        }
    }
    return cnt;
}
signed main() {
    std::cin>>n>>K;
    rep(i,1,n) {
        rep(j,1,n) {
            std::cin>>c[i][j];
        }
    }
    mem(dp,0x3f);
    dp[(1<<n)-1]=0;
    dep(i,(1<<n)-1,1) {
        rep(j,1,n) {
            if((i>>j-1)&1){
                continue;
            }
            rep(k,1,n) {
                if(!((i>>k-1)&1)) {
                    continue;
                }
                dp[i]=std::min(dp[i],dp[i|(1<<j-1)]+c[j][k]);
            }
        }
    }
    rep(i,1,(1<<n)-1) {
        if(calc(i)<=K) {
            ans=std::min(ans,dp[i]);
        }
    }
    std::cout<<ans;
    return 0;
}

http://www.niftyadmin.cn/n/5448259.html

相关文章

详解rtklib中main函数如何配置文件(下)

目录 一、main函数流程总结 二、分析识别 -k 后如何配置 三、最后传参的数据文件处理方式 一、main函数流程总结 详解rtklib中main函数如何配置文件&#xff08;上&#xff09;-CSDN博客 在这片文章中讲解了rtklib中main函数的整个流程。 &#xff08;1&#xff09;通过…

了解Spring:Java开发的利器

Spring是一款开源的轻量级Java开发框架&#xff0c;旨在提高开发人员的效率和系统的可维护性。本文将介绍Spring的基本概念、使用优势、设计模式以及与Spring MVC和Spring Boot的关联。 什么是Spring&#xff1f; Spring是一款开源的轻量级Java开发框架&#xff0c;它由多个模…

spring-boot解析spring.factories文件

spring-boot解析spring.factories文件 启动SpringBoot自动装配的工厂类方法实现 /*** 解析 spring.factories 文件** return 读取到的所有数据*/private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader){try {Enumeration<URL…

(第78天)DB RU 补丁升级:19C 升级到 19.22

前言 目前 Oracle 19C 是最新的稳定支持的版本,生产环境中使用的越来越多。当然,随着客户使用量的增多,自然无可避免的产生了很多 BUG,Oracle 每季度都会发布一个 RU 补丁来修复当前季度所产生的一些重要 BUG 补丁。作为 DBA,DB 补丁修复必然是需要掌握的一项技能。 本文…

如何在MySQL中实现基于时间点的恢复?

在MySQL中实现基于时间点的数据恢复是一种用于找回在特定时间点前数据库状态的高级恢复技术。这通常在发生数据误删、更新错误或其他数据损失情况时非常有用。以下是实现基于时间点恢复的一般步骤&#xff1a; ### 准备工作 1. 启用二进制日志 - 首先确保MySQL服务器配置已经…

【Andriod】美团组件化路由框架WMRouter源码解析

前言 Android无论App开发还是SDK开发&#xff0c;都绕不开组件化&#xff0c;组件化要解决的最大的问题就是组件之间的通信&#xff0c;即路由框架。国内使用最多的两个路由框架一个是阿里的ARouter&#xff0c;另一个是美团的WMRouter。这两个路由框架功能都很强大&#xff0…

【机器学习】BP神经网络Matlab实现

目录 1.背景2.原理3.代码实现 1.背景 BP神经网络&#xff08;Backpropagation Neural Network&#xff09;是一种机器学习算法&#xff0c;其通过反向传播算法来训练网络&#xff0c;使其能够学习输入数据的模式并进行预测或分类任务。BP神经网络通常包括输入层、隐藏层和输出…

TCP重传机制详解——02SACK

文章目录 TCP重传机制详解——02 SACKSACK是什么&#xff1f;为什么要有SACK&#xff1f;实际场景抓包具体显示信息流程 实战抓包讲解SACK关闭场景下&#xff0c;三次重复ACK后会快速重传SACK打开但是不携带SACK块信息场景下&#xff0c;三次重复ACK也不会快速重传SACK打开并且…