将数组划分为 K 个差异最小的子数组

2023-11-26

免责声明:

所描述的问题看起来像是竞赛中的任务。我没有参加任何一个,我不知道任何正在进行的比赛,这可能涉及这个问题。如果有的话,我会结束这个问题以保持公平!

我有个问题: 给定一个由值和整数 K 组成的数组 A,将 A 拆分为恰好 K 个不重叠的连续子数组,使得具有最小和的子数组与具有最大和的子数组之间的差异最小。允许将 A 向任意方向旋转任意数量。

考虑一个例子:

输入:A = [5 1 1 1 3 2],K = 3

输出:[5][1 1 1][3 2],最大和 = 5,最小和 = 3,结果 = 2

我有部分工作的代码(非常丑陋,我的错,但这并不意味着生产质量):

#include <climits>
#include <cstdio>
#include <cstring>

const int max_n = 50;
const int max_k = 20;

int deps[max_n];

int max (int x, int y) {
  return x > y ? x : y;
}

int min (int x, int y) {
  return x < y ? x : y;
}

int sum (int a[], int start, int end) {
  int res = 0;
  for (int i = start; i <= end; ++i) res += a[i];

  return res;
}

int k_partitioning(int k, int n, int deps[]) {
  int res = INT_MAX;
  // consider all possible rotations/shifts
  for(int offset = 0; offset < n; ++offset) {
    for(int l_min = 0; l_min < n; ++l_min) {
      for(int r_min = l_min; r_min < n; ++r_min) {
        // check minimal sum subarray
        int min_sum = sum (deps, l_min, r_min);

        int dp[k][n];
        for (int s = 0; s < k; ++s) {
          for (int q = 0; q < n; ++q) {
            dp[s][q] = 0;
          }
        }
        // assuming that current sum is a target sum
        dp[0][r_min-l_min] = min_sum;

        for(int p = 1; p < k; ++p) {
          for(int l_max = 0; l_max < n; ++l_max) {
            for(int r_max = 0; r_max < n; ++r_max) {
              int max_sum = sum(deps, l_max, r_max);

              if (max_sum >= min_sum) dp[p][r_max] = max(dp[p-1][l_max], max_sum);
            } // l_maxs
          } // r_maxs
        } // partitions
        // printing dp

        // skip incorrect partitioning, when not all K partitions were used
        if (dp[k-1][n-1] == 0) continue;

        // update difference
        res = min (res, dp[k-1][n-1] - min_sum);
      } // end min sum seg
    } // start min sum seg
    //break;
  } // cuts
  return res;
}

int main(int argc, char* argv[]) {
  int k = 0;
  scanf("%d", &k);

  int n = 0;
  scanf("%d", &n);

  for (int i = 0; i < n; ++i) {
    scanf("%d", &deps[i]);
  }

  printf ("%d\n", k_partitioning(k, n, deps));

  return 0;
}

这个想法很简单:假设当前分区具有最小总和,枚举所有可能的最大分区,设置动态编程以生成具有最小值的最大总和,检查差异。总复杂度:O(K*N^4)。

我的问题是它未能通过一些测试,并且我一直在解决它。有人可以帮我吗?

测试失败,例如:

N = 4,K = 2,A = [6 13 10 2]

UPDATE

此版本应该修复一些以前的问题。首先,它删除了“偏移量”上的浪费循环,并在 l_min 循环末尾添加了一个数组旋转。其次,我注意到, dp 不能用 0 初始化 - 这是最小化任务,因此应该用一些大值初始化(取决于问题的常量,这里的 max_value 已经超出值域)。最后,间隔不应再重叠 - 每个总和不包括间隔的左端。然而,它仍然没有产生预期的结果。

#include <climits>
#include <cstdio>
#include <cstring>

const int max_value = 200000;
const int max_n = 50;
const int max_k = 20;

int deps[max_n];

int max (int x, int y) {
  return x > y ? x : y;
}

int min (int x, int y) {
  return x < y ? x : y;
}

int sum (int a[], int start, int end) {
  int res = 0;
  for (int i = start; i <= end; ++i) res += a[i];

  return res;
}

int k_partitioning(int k, int n, int deps[]) {
  int res = max_value;

  for(int l_min = 0; l_min < n; ++l_min) {
    for(int r_min = l_min; r_min < n; ++r_min) {
      int min_sum = sum (deps, l_min+1, r_min);

      int dp[k][n];
      for (int s = 0; s < k; ++s) {
        for (int q = 0; q < n; ++q) {
          dp[s][q] = max_value;
        }
      }
      // assuming that current sum is a target sum
      dp[0][r_min-l_min] = min_sum;

      for(int p = 1; p < k; ++p) {
        for(int l_max = 0; l_max < n; ++l_max) {
          for(int r_max = l_max; r_max < n; ++r_max) {
            int max_sum = sum(deps, l_max+1, r_max);

            if (max_sum >= min_sum) dp[p][r_max] = max(dp[p-1][l_max], max_sum);
          } // l_maxs
        } // r_maxs
      } // partitions

      // skip incorrect partitioning, when not all K partitions were used
      if (dp[k-1][n-1] == max_value) continue;

      // update difference
      res = min (res, dp[k-1][n-1] - min_sum);
    } // end min sum seg

    // rotate an array to consider different starting points
    int tmp[n];
    for (int i = 0; i < n; ++i) {
      int new_idx = i + n + 1;

      tmp[new_idx % n] = deps[i];
    }

    for(int i = 0; i < n; ++i) deps[i] = tmp[i];
  } // start min sum seg

  return res;
}

int main(int argc, char* argv[]) {
  int k = 0;
  scanf("%d", &k);

  int n = 0;
  scanf("%d", &n);

  for (int i = 0; i < n; ++i) {
    scanf("%d", &deps[i]);
  }

  printf ("%d\n", k_partitioning(k, n, deps));

  return 0;
}

好吧,我想我做到了!

想法如下:我们假设最小和区间总是从0开始。然后我们从最小区间的右边界开始枚举最大和区间。我们为当前最大间隔构建 DP 问题以确定最小最大和。之后,更新结果并将数组旋转 1。

我的代码在每次迭代计算当前总和的方式上并不完美。人们可以预先计算它们并每次只对它们进行索引。

这段代码可能有一些错误,但它通过了我的所有测试。

#include <climits>
#include <cstdio>
#include <cstring>

const int max_value = 200000;
const int max_n = 50;
const int max_k = 20;

int deps[max_n];

int max (int x, int y) {
  return x > y ? x : y;
}

int min (int x, int y) {
  return x < y ? x : y;
}

int sum (int a[], int start, int end) {
  int res = 0;

  for (int i = start; i <= end; ++i) res += a[i];

  return res;
}

int k_partitioning(int k, int n, int deps[]) {
  int res = max_value;
  for(int offset = 0; offset < n; ++offset) {
    int l_min = 0;
    for(int r_min = l_min; r_min < n; ++r_min) {
      int min_sum = sum (deps, l_min, r_min);

      int dp[k][n];
      for (int s = 0; s < k; ++s) {
        for (int q = 0; q < n; ++q) {
          dp[s][q] = max_value;
        }
      }
      // assuming that current sum is a target sum
      dp[0][r_min-l_min] = min_sum;

      for(int p = 1; p < k; ++p) {
        for(int l_max = r_min; l_max < n; ++l_max) {
          for(int r_max = l_max; r_max < n; ++r_max) {
            int max_sum = sum(deps, l_max+1, r_max);

            if (max_sum >= min_sum) {
              dp[p][r_max] = min(dp[p][r_max], max(dp[p-1][l_max], max_sum));
            }

          } // l_maxs
        } // r_maxs
      } // partitions

      // skip incorrect partitioning, when not all K partitions were used
      if (dp[k-1][n-1] == max_value) continue;

      // update difference
      res = min (res, dp[k-1][n-1] - min_sum);
    } // end min sum seg
    int tmp[n];
    for (int i = 0; i < n; ++i) {
      int new_idx = i + n - 1;

      tmp[new_idx % n] = deps[i];
    }

    for(int i = 0; i < n; ++i) deps[i] = tmp[i];

  } // start min sum seg
  return res;
}

int main(int argc, char* argv[]) {
  int k = 0;
  scanf("%d", &k);

  int n = 0;
  scanf("%d", &n);

  for (int i = 0; i < n; ++i) {
    scanf("%d", &deps[i]);
  }

  printf ("%d\n", k_partitioning(k, n, deps));

  return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将数组划分为 K 个差异最小的子数组 的相关文章

  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • 在 Xamarin Android 中将图像从 URL 异步加载到 ImageView 中

    我有一个包含多个项目的 ListView 列表中的每个项目都应该有一个与之关联的图像 我创建了一个数组适配器来保存每个列表项并具有我希望加载的图像的 url 我正在尝试使用 Web 请求异步加载图像 并设置图像并在加载后在视图中更新它 但视
  • 如何在没有 Control.Invoke() 的情况下从后台线程修改控件属性

    最近 我们遇到了一些旧版 WinForms 应用程序 我们需要更新一些新功能 在专家测试该应用程序时 发现一些旧功能被破坏 无效的跨线程操作 现在 在您认为我是新手之前 我确实有一些 Windows 窗体应用程序的经验 我不是专家 但我认为
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 按字典顺序对整数数组进行排序 C++

    我想按字典顺序对一个大整数数组 例如 100 万个元素 进行排序 Example input 100 21 22 99 1 927 sorted 1 100 21 22 927 99 我用最简单的方法做到了 将所有数字转换为字符串 非常昂贵
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • 将变量分配给另一个变量,并将一个变量的更改反映到另一个变量中

    是否可以将一个变量分配给另一个变量 并且当您更改第二个变量时 更改会瀑布式下降到第一个变量 像这样 int a 0 int b a b 1 现在 b 和 a 都 1 我问这个问题的原因是因为我有 4 个要跟踪的对象 并且我使用名为 curr
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co

随机推荐

  • Python:AttributeError:“NoneType”对象没有属性“append”[重复]

    这个问题在这里已经有答案了 我的程序看起来像 global item to bucket list map def fill item bucket map items buckets global item to bucket list
  • 数据绑定文本框:无法退出

    我在表单上有一个绑定到对象属性 实际上是几个文本框 的文本框 这是一个对象的编辑器 当我编辑某些对象并修改其中一个文本框中的值时 我无法从文本框退出 无论是通过选项卡还是单击另一个文本框 然而情况并非总是如此 当编辑其他对象 相同类型 时它
  • Android:如何使用SDK向SIM卡添加联系人?

    我正在编写一个应用程序 将联系人写入 Android 手机的 SIM 卡中 我被困在添加电话号码的地方 发生异常 没有明显的原因 这是一段代码 import android app Activity import android conte
  • 正则表达式验证属性无法正常工作

    我想验证视图模型中的属性以匹配正则表达式 视图模型 using System ComponentModel DataAnnotations namespace ProjectName ViewModels public class View
  • 在 Java 中更改 XML 文件中的一个值的最佳方法是什么?

    我有一个 XML 文件 并且我知道需要更改其值的节点名称 节点名称是 ipAddress 我可以使用 JDOM 获取文档 获取节点 更改值并写入它 或者我可以编写 XSLT 文件 代码更改值来自 Java 所以我的问题是哪个选项更好 XML
  • Tensorflow的非对称填充假设

    为什么 TensorFlow 选择在右下角填充 With SAME填充 对我来说 在第一个真实像素处启动内核的中心锚点是合乎逻辑的 由于使用了不对称填充 这导致与其他一些框架存在差异 我确实明白 原则上不对称填充是好的 因为否则会留下未使用
  • 在 M 天内阅读 N 章书籍的最佳方式

    我遇到过这样一个面试问题 给定一本有 N 章的书 当然每章的页数不同 在必须读完一章的限制下 在 M 天内完成整本书的最佳方法是什么同一天 例子 Chapters 7 5 3 9 10 Days 4 人们应该读一下 Chapter1 on
  • 将现有 Microsoft.AspNet.Identity DB (EF 6) 迁移到 Microsoft.AspNetCore.Identity (EF Core)

    我正在开发一个应用程序 APS net MVC 它使用微软 AspNet Identity 现在我想将我的应用程序修改为 APS net Core 它使用微软 AspNetCore Identity 但这两者在每个模型上都有一些差异 有没有
  • 最新的react-hook-form错误处理与material-ui TextField

    我在使用react hook form 和material ui 时遇到了困难 我准备了一个代码沙盒示例 import TextField from material ui core import React from react impo
  • 多个读者同步,单个作者?

    另一个同步问题 我希望你们不要生气 假设以下场景 一个中心数据结构 非常大 所以我真的不想使其不可变并在发生更改时复制它 我什至不想在内存中保留多个副本 多个读取器线程以只读方式访问该数据结构 并有一个写入器线程在后台保持数据结构最新 我目
  • lua 64位转换问题

    我真的希望对这个主题有一些帮助 有人在需要同时支持 32 位和 64 位的应用程序中使用过 lua 吗 我们目前正在过渡到 64 位 但客户端编译的 lua 脚本遇到了问题 我们无法使用 64 位版本重新编译 因此 实际上我们需要能够在 6
  • IE 不提供保存 ASP.NET 表单的密码

    有时微软会做出一些非常愚蠢的事情 让我头疼 帮我看看事实并非如此 拜托 我正在开发的 ASP NET 3 5 站点的登录页面存在问题 IE 7 或 8 无法忍受打开 6 在用户登录 我检查了其他浏览器 Firefox Chrome 和 Sa
  • laravel安装ui时出现问题如何解决?

    安装 laravel ui 时出现以下错误 Using version 2 0 for laravel ui Problem 1 Conclusion remove laravel framework v6 18 0 Conclusion
  • ModuleNotFoundError:没有名为“google.cloud”的模块

    我正在寻找使用 Google 云文本到语音 API 但遇到了找不到模块的常见问题 我已经尝试过大多数人都有的解决方案 唯一的问题是我使用 Windows 而大多数解决方案都是针对 mac 或 Linux 的 尽管这不应该是一个大问题 我在命
  • Zend Framework:在引导程序中获取请求对象

    如何从引导文件中获取请求对象 我可以尝试这个方法 但不起作用 request new Zend Controller Request Http request Zend Controller FrontController getInsta
  • 如何从 VS2010 立即窗口调用 F# 函数

    在调试 F 应用程序时 我希望能够从 VS2010 立即窗口调用 F 方法 但它似乎不起作用 问题似乎是 F 方法实际上是 FSharpFunc 对象 我尝试使用 Invoke 方法 但交互式窗口无法识别它 Visual Studio 的
  • python odo sql AssertionError: datashape 必须是 Record 类型,得到 0 * {...}

    我正在尝试使用 odo 将 CSV 导入 MySQL 但收到数据形状错误 我的理解是 datashape 采用以下格式 var column type 其中 var 表示可变的行数 我收到以下错误 AssertionError datash
  • Android:如何仅在安装应用程序时调用方法

    我需要调用一个方法 或启动一个活动 或其他方法 来更新包含应用程序所需数据的文件 但我希望它只在第一次安装应用程序时完成一次 因为之后我会自己处理文件的更新 请问怎样才能做到呢 感谢您的任何建议 要在应用程序中只执行一次某件事 您需要这样的
  • jsp中如何显示带有标签的文本

    我想显示一个名为 welcome
  • 将数组划分为 K 个差异最小的子数组

    免责声明 所描述的问题看起来像是竞赛中的任务 我没有参加任何一个 我不知道任何正在进行的比赛 这可能涉及这个问题 如果有的话 我会结束这个问题以保持公平 我有个问题 给定一个由值和整数 K 组成的数组 A 将 A 拆分为恰好 K 个不重叠的