【zzuli-2259】matrix

针对一个给定的数值集合及矩阵尺寸,通过选取合适的数值填充矩阵以求得矩阵的最小法值。采用二分查找结合滑动窗口的方法,实现高效求解。

【zzuli-2259】matrix

题目描述

在麦克雷的面前有N个数,以及一个R*C的矩阵。现在他的任务是从N个数中取出 R*C 个,并填入这个矩阵中。矩阵每一行的法值为本行最大值与最小值的差,而整个矩阵的法值为每一行的法值的最大值。现在,麦克雷想知道矩阵的最小法值是多少。

输入

输入共两行。

第一行是三个整数:n,r,c。(r, c <= 104, r * c <= n <= 106)

第二行是 n 个整数 Pi。(0 < pi <= 109)

输出

输出一个整数,即满足条件的最小的法值。

样例输入

7 2 3
170 205 225 190 260 225 160

样例输出

30

引用殷大佬一句话,「最大最小值我一看就是二分」....orz

首先每一行的元素一定是连续的,但是不同行的元素可以不连续,这点很容易想明白。求min,等号应该加在r = mid - 1,答案是l。然后题目就变成了判断一个数是否是一个矩阵的法值,方法是枚举每个长度为c的行看看max-min是否<=法值,满足r个则成立,否则不成立。

 

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+4;
int mp[N], a[N], R, c, n;
bool ok(int x)
{
    int num = 0;
    for(int i = c; i <= n; i++)
    {
        if(a[i] <= x) //等号体现在这里
        {
            i = i+c-1;
            num++;
        }
        if(num == R) return 1;
    }
    return 0;
}
int main()
{
    cin>>n>>R>>c;
    for(int i = 1; i <= n; i++) scanf("%d", &mp[i]);
    sort(mp+1, mp+1+n);
    for(int i = c; i <= n; i++) a[i] = mp[i] - mp[i-c+1];
    int l = 0, r = 1e9;
    while(l <= r)
    {
        int mid = (l+r)>>1;
        if(ok(mid))
            r = mid - 1;
        else
            l = mid + 1;
    }
    printf("%d\n", l);
    return 0;
}

 

posted @ 2018-04-30 17:46 LesRoad 阅读(...) 评论(...) 编辑 收藏

下载方式:https://pan.quark.cn/s/a4b39357ea24 布线问题(分支限界算法)是计算机科学和电子工程领域中一个广为人知的议题,它主要探讨如何在印刷电路板上定位两个节点间最短的连接路径。 在这一议题中,电路板被构建为一个包含 n×m 个方格的矩阵,每个方格能够被界定为可通行或不可通行,其核心任务是定位从初始点到最终点的最短路径。 分支限界算法是处理布线问题的一种常用策略。 该算法与回溯法有相似之处,但存在差异,分支限界法仅需获取满足约束条件的一个最优路径,并按照广度优先或最小成本优先的原则来探索解空间树。 树 T 被构建为子集树或排列树,在探索过程中,每个节点仅被赋予一次成为扩展节点的机会,且会一次性生成其全部子节点。 针对布线问题的解决,队列式分支限界法可以被采用。 从起始位置 a 出发,将其设定为首个扩展节点,并将与该扩展节点相邻且可通行的方格加入至活跃节点队列中,将这些方格标记为 1,即从起始方格 a 到这些方格的距离为 1。 随后,从活跃节点队列中提取队首节点作为下一个扩展节点,并将与当前扩展节点相邻且未标记的方格标记为 2,随后将这些方格存入活跃节点队列。 这一过程将持续进行,直至算法探测到目标方格 b 或活跃节点队列为空。 在实现上述算法时,必须定义一个类 Position 来表征电路板上方格的位置,其成员 row 和 col 分别指示方格所在的行和列。 在方格位置上,布线能够沿右、下、左、上四个方向展开。 这四个方向的移动分别被记为 0、1、2、3。 下述表格中,offset[i].row 和 offset[i].col(i=0,1,2,3)分别提供了沿这四个方向前进 1 步相对于当前方格的相对位移。 在 Java 编程语言中,可以使用二维数组...
源码来自:https://pan.quark.cn/s/a4b39357ea24 在VC++开发过程中,对话框(CDialog)作为典型的用户界面组件,承担着与用户进行信息交互的重要角色。 在VS2008SP1的开发环境中,常常需要满足为对话框配置个性化背景图片的需求,以此来优化用户的操作体验。 本案例将系统性地阐述在CDialog框架下如何达成这一功能。 首先,需要在资源设计工具中构建一个新的对话框资源。 具体操作是在Visual Studio平台中,进入资源视图(Resource View)界面,定位到对话框(Dialog)分支,通过右键选择“插入对话框”(Insert Dialog)选项。 完成对话框内控件的布局设计后,对对话框资源进行保存。 随后,将着手进行背景图片的载入工作。 通常有两种主要的技术路径:1. **运用位图控件(CStatic)**:在对话框界面中嵌入一个CStatic控件,并将其属性设置为BST_OWNERDRAW,从而具备自主控制绘制过程的权限。 在对话框的类定义中,需要重写OnPaint()函数,负责调用图片资源并借助CDC对象将其渲染到对话框表面。 此外,必须合理处理WM_CTLCOLORSTATIC消息,确保背景图片的展示不会受到其他界面元素的干扰。 ```cppvoid CMyDialog::OnPaint(){ CPaintDC dc(this); // 生成设备上下文对象 CBitmap bitmap; bitmap.LoadBitmap(IDC_BITMAP_BACKGROUND); // 获取背景图片资源 CDC memDC; memDC.CreateCompatibleDC(&dc); CBitmap* pOldBitmap = m...
### ZZULIOJ 1126 布尔矩阵奇偶性解题思路 对于给定的一个n阶布尔方阵,要判断其是否具有奇偶均势特性,即每行、每列总和为偶数[^3]。如果该矩阵不满足此条件,则进一步检查能否通过改变其中一个元素(0变为1或1变为0),使得整个矩阵达到奇偶均势。 #### 判断原始矩阵是否符合条件 遍历整个矩阵计算各行各列的1的数量,并记录下这些数量中为奇数的情况。若所有行列都含有偶数个1,则直接输出“OK”。 #### 尝试修正一次错误的可能性 当发现存在某一行或某一列为奇数时,考虑是否存在唯一的位置可以调整从而让所有的行与列都能变成偶数之和。具体做法如下: - 统计有多少行以及多少列出现了奇数次的1; - 如果恰好只有一个位置能够同时影响到两个方向上由奇转偶,则说明可以通过更改这一个位来修复矩阵; - 输出需要变更的具体坐标`bit(i, j)`,其中i表示第几行,j表示第几列,注意这里的索引是从0开始编号的。 #### 处理无法修复的情形 经过上述两步处理之后仍然未能得到满意的结果,则表明当前输入数据已经损坏严重,无法简单地通过单点变换恢复成合法状态,此时应返回字符串“Corrupt”。 ```cpp #include <iostream> using namespace std; int main() { int n; cin >> n; bool matrix[n][n]; int rowSum[n], colSum[n]; // 初始化rowSum 和 colSum 数组 for(int i = 0; i < n; ++i){ rowSum[i]=colSum[i]=0; } // 输入矩阵的同时统计各行各列中的'1' for(int i=0;i<n;++i){ for(int j=0;j<n;++j){ cin>>matrix[i][j]; rowSum[i]+=matrix[i][j]; colSum[j]+=matrix[i][j]; } } int oddRow=-1,oddCol=-1,rowCount=0,colCount=0; // 记录哪些行/列有奇数个‘1’及其总数目 for(int i=0;i<n;++i){ if(rowSum[i]%2!=0){ rowCount++; oddRow=i;} if(colSum[i]%2!=0){ colCount++; oddCol=i;} } // 根据不同情况给出相应结果 if((rowCount==0)&&(colCount==0)){ cout<<"OK"; }else if ((rowCount<=1)&&(colCount<=1)){ cout << "Change bit("<<oddRow<<","<<oddCol<<")"; } else{ cout <<"Corrupt"; } return 0; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值