`

bitmap求哈密顿距离-给定N(1<=N<=100000)个五维的点A(x1,x2,x3,x4,x5),求两个点X(x1,x2,x3,x4,x5)和Y(

阅读更多
import java.util.Random;

/**
 * 题目:
 * 给定N(1<=N<=100000)个五维的点A(x1,x2,x3,x4,x5),求两个点X(x1,x2,x3,x4,x5)和Y(y1,y2,y3,y4,y5),
 * 使得他们的哈密顿距离(d=|x1-y1| + |x2-y2| + |x3-y3| + |x4-y4| + |x5-y5|)最大。|x|=abs(x)。
 * 
 * 第一种方法当然是暴力遍历一次,求得最大值
 * 第二种方法借助bitmap
 * 在网上找了两个相关的资料:
 * http://www.cppblog.com/sonicmisora/archive/2009/09/14/96143.aspx
 * http://wenku.baidu.com/view/1e51750abb68a98271fefaa8.html
 * 
 * 我觉得这两个资料都不好理解
 * 我的理解如下:
 * 1.
 * 这道题目里面,使用bitmap的关键是这个:
 * 先看二维的点,我们约定形如Xij下标的数字(ij)是二进制,0表示正数,1表示负数,令
 * X00=   x1 + x2
 * X01=   x1 - x2
 * X10= - x1 + x2
 * X11= - x1 - x2
 * 用一个一维数组a保存这四个值,即a[0]=X00,a[1]=X01,a[2]=X10,a[3]=X11
 * 有N个点,那么就有二维数组:A[N][S],(S=00,01,10,11)
 * 
 * 2.(当然,更严谨的数学证明请参考上面提到的第二个链接)
 *    |x1-y1| = MAX(x1-y1, y1-x1);
 * => |x1-y1| + |x2-y2| = 
                           MAX{
                              (x1-y1)+(x2-y2)
                              (x1-y1)-(x2-y2)
                             -(x1-y1)+(x2-y2)
                             -(x1-y1)-(x2-y2)
                             
                           };
                  也就是=
                           MAX{
                              (x1+x2)-(y1+y2)
                              (x1-x2)-(y1-y2)
                              (-x1+x2)-(-y1+y2)
                              (-x1-x2)-(-y1-y2)
                           };
   正好是MAX{(X00-Y00), (X01-Y01), (X10-Y10), (X11-Y11)};
   如果有A-Z共26个点,那么
   result = MAX{
               (A00-B00), (A01-B01), (A10-B10), (A11-B11),
               (A00-C00), (A01-C01), (A10-C10), (A11-C11),
               ......
               (X00-Y00), (X01-Y01), (X10-Y10), (X11-Y11),
               (Y00-Z00), (Y01-Z01), (Y10-Z10), (Y11-Z11),
   };
   对上面的每一列应用MAX运算:
   对ij=00,时,第一列有MAX(第一列)=MAX(A00,B00...Z00) - Min(A00,B00...Z00)
   那么 result = MAX{MAX(第一列),MAX(第二列)...};
   
   也就是上面提到的第一个链接里面的说法,引用一下:
   A[1][0]-A[2][0]
   A[1][1]-A[2][1]
   A[1][2]-A[2][2]
   A[1][3]-A[2][3] 
   然后问题就变得简单了,扫一遍,对于每个I,求出A[*][I]的最大值MAX(I)最小值MIN(I),
   再用MAX(I)-MIN(I)就可以得到对于I来说的最大值了。最后取个总的最大值

 * @author bylijinnan
 */
public class HamiltonDistance {

    private final int N = 10 * 1000;
    private final int D = 5;
    private final int S = 1 << D;

    public static void main(String[] args) {
        HamiltonDistance h = new HamiltonDistance();
        h.test();
    }

    public void test() {
        int[][] data = sourceData();
        System.out.println(maxHamiltonDistance(data));
        System.out.println(maxHamiltonDistanceBitMap(data));
    }
    
    /**
     * 通过枚举暴力求解
     * @param data
     * @return
     */
    public long maxHamiltonDistance(int[][] data) {
        if (data == null || data.length != N || data[0].length != D) {
            System.out.println("invalid input");
            return 0L;
        }
        long result = 0L;
        for(int i = 0; i < N; i++) {
            int[] pointA = data[i];
            for(int j = i + 1; j < N; j++) {
                int[] pointB = data[j];
                long distance = distanceOfTwoPoints(pointA, pointB);
                if (result < distance) {
                    result = distance;
                }
            }
        }
        return result;
    }
    
    //求得:|X1-Y1| + |X2-Y2| + |X3-Y3| + |X4-Y4| + |X5-Y5| + ...|Xn-Yn|
    private long distanceOfTwoPoints(int[] pointA, int[] pointB) {
        long result = 0L;
        for(int i = 0; i < D; i++) {
            result += Math.abs((long)pointA[i] - (long)pointB[i]);
        }
        return result;
    }
    
    /**
     * 通过bitmap求解
     * @param data
     * @return
     */
    public long maxHamiltonDistanceBitMap(int[][] data) {
        //略去输入合法性检查
        long result = Long.MIN_VALUE;
        
        //求得X00000~X11111,下标是二进制
        long[][] A = new long[N][S];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < S; j++) {
                A[i][j] = getSumByBits(data[i], j);
            }
        }
        
        //System.out.println(Arrays.deepToString(A));
        
        long MAXi = Long.MIN_VALUE;
        long MINi = Long.MAX_VALUE;
        for (int i = 0; i < S; i++) {
            for (int j = 0; j < N; j++) {
                if (MAXi < A[j][i]) {
                    MAXi = A[j][i];
                }
                if (MINi > A[j][i]) {
                    MINi = A[j][i];
                }
            }
            result = max(result, (MAXi - MINi));
            MAXi = Long.MIN_VALUE;
            MINi = Long.MAX_VALUE;
        }
        return result;
    }
    
    //0表示正数,1表示负数
    private long getSumByBits(int[] a, int s) {
        long result = 0L;
        for (int i = 0; i < D; i++) {
            if (exist(s, i)) {
                result -= a[i];
            } else {
                result += a[i];
            }
        }
        return result;
    }

    //value的二进制表示,在第offset位是否为1
    private boolean exist(int value, int offset) {
        //return (value & (1 << offset)) == 1;
        return (value & (1 << offset)) != 0;
    }
    
    //生成指定维度的N个点
    private int[][] sourceData() {
        int[][] data = new int[N][D];
        Random random = new Random();
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < D; j++) {
                int value = random.nextInt();
                data[i][j] = value;
            }
        }
        return data;
    }
    
    
    private long max(long x, long...yy) {
        long result = x;
        for(long y : yy) {
            if (result < y) {
                result = y;
            }
        }
        return result;
    }
    
}
0
7
分享到:
评论

相关推荐

    基于MFC的滤波器,分别实现了三种方法的滤波

    公式可以表示为 `y[n] = (1 - α) * y[n-1] + α * x[n]`,其中 `α` 是衰减因子,`x[n]` 是当前输入,`y[n]` 和 `y[n-1]` 是连续输出。在MFC中,你可以创建一个循环结构,每次迭代更新输出值: ```cpp double ...

    视屏截图代码

    if (bitmap.bmBitsPixel&lt;16) //判断是否为真彩色位图 panelsize = pow(2,bitmap.bmBitsPixel*sizeof(RGBQUAD)); BITMAPINFO *pBInfo = (BITMAPINFO*)LocalAlloc(LPTR,sizeof(BITMAPINFO)+panelsize); ...

    JavaJavaScript网页设计活学活用300问源文件-020

    从给定的文件信息中,我们可以提取到一系列与Java Applet相关的网页设计知识点,主要涉及了如何在HTML页面中嵌入Java Applet以及通过参数控制其行为和外观。以下是详细的知识点总结: ### Java Applet网页设计:...

    bitmap-fixed-fonts-0.3-28.el8.noarch(1).rpm

    离线安装包,亲测可用

    bitmapfont-for-ugui

    《UGUI中的BitmapFont应用详解》 在Unity的UI系统中,UGUI(Unity Graphic User Interface)是一个强大的工具,用于创建交互式用户界面。而BitmapFont则是UGUI中一种特殊的字体资源,它允许开发者使用自定义的位图...

    雅虎TAB效果代码 Javascript实现

    --[if lte IE 6]&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/a&gt;&lt;![endif]--&gt; &lt;/li&gt; &lt;/ul&gt; &lt;br class="clear" /&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="#nogo" class="four outer"&gt;SEARCH&lt;!--[if IE 7]&gt;&lt;!--&gt;&lt;/a&gt;&lt;!--&lt;![endif]--&gt; &lt;!--[if lte IE 6]&gt;&lt;table&gt;...

    图片文字按钮

    &lt;bitmap android:src="@drawable/button_image" android:gravity="center" /&gt; &lt;/item&gt; &lt;!-- 文字部分 --&gt; &lt;item&gt; &lt;inset android:insetLeft="16dp" &lt;!-- 文字与图片左侧的距离 --&gt; android:insetTop="8dp" ...

    C# Bitmap转RGB32(NI)

    在图像处理领域,C# 和 National Instruments (NI) Vision 是两个常见的工具,它们在工业自动化、机器视觉和其他图像分析应用中发挥着重要作用。本主题主要关注如何在C#环境中将Bitmap对象转换为RGB32格式,以便与NI...

    窗口化,均值,中值滤波

    this-&gt;Image1-&gt;Picture-&gt;Bitmap-&gt;Canvas-&gt;Pixels[i][j] = RGB(color1, color1, color1); } } ``` 需要注意的是,这里的代码仅实现了部分中值滤波的功能,且仅考虑了红色通道。在实际应用中,通常需要对RGB三个通道...

    Android 实现把bitmap图片的某一部分的颜色改成其他颜色

    if ((90&lt;r&&r&lt;=200)&&(90&lt;g&&g&lt;=200)&&(90&lt;b&&b&lt;=200)){//大概得把非道路(路旁变透明) a=0; Log.i("imagecolor","============"+color); }else if (r==255&&g==255&&b==33){//把黄色的箭头白色 因为黄色箭头...

    数字图像的简单代码

    这段代码实现了3x3的均值滤波器,计算每个像素周围8个邻域像素的平均值,然后将结果赋给当前像素。 总的来说,通过BCB进行数字图像处理,初学者需要理解图像的基本概念,学会使用图形库进行图像操作,包括加载、...

    电子科大数字图象处理实验_BMP_灰度_直方图均衡_均值滤波

    1.把24位BMP变灰度图像 2.进行直方图均衡化,提高图像对比度 3.进行均值滤波 第二个均衡化做了N天。。。每天回寝室看一眼以为是算法错了。。后来终于发现是一个溢出的小错误,duang。。这都是假的。。是特技的溢出。...

    Android中Glide获取图片Path、Bitmap用法详解

    软件开发网在此之前给大家介绍过图片加载框架Glide的基本用法介绍,大家可以先参考一下,本篇内容更加深入的分析了Glide获取图片Path、Bitmap用法,以及实现的代码分析。 1. 获取Bitmap: 1)在图片下载缓存好之后...

    二进制资源占用说明文档-Bitmap_indexes_-_Marko_Kevac.pdf

    根据提供的文件内容,此文档似乎是关于二进制资源占用和Bitmap索引的介绍和讲解,主要以Marko Kevac在Gophercon Russia 2019的分享为基础。以下是关于标题和描述中的知识点的详细说明: 1. Bitmap索引的概念: ...

    标示路面黄线

    if (c.R &gt;= 240 && c.R &lt;= 255 && c.G &gt;= 240 && c.G &lt;= 255 && c.B &gt;= 240 && c.B &lt;= 255) { p.SetPixel(i, j, Color.Green); count[i, j] = 1; } if (c.R &gt;= 200 && c.R &lt;= 250 && c.G &gt;= 150 && c.G &lt;= 250...

    Android-使用Matrix对Bitmap进行处理

    Matrix会根据给定的变换规则对图像进行处理,生成一个新的Bitmap。例如,以下代码展示了如何使用Matrix旋转Bitmap: ```java Bitmap originalBitmap = ...; // 原始Bitmap Matrix matrix = new Matrix(); matrix....

    开源项目-seiflotfy-s-bitmap.zip

    开源项目-seiflotfy-s-bitmap.zip,S-Bitmap: Distinct Counting with a Self-Learning Bitmap (an equivalent to HyperLogLog) implemented in Go

    剪切板查看 clipboard viewer,查看剪贴板中有那些格式,并可以查看每种格式的内容 默认显示CF-UNICODETE

    剪切板查看 clipboard viewer,查看剪贴板中有那些格式,并可以查看每种格式的内容。默认显示CF_UNICODETEXT,CF_HTML,CF_BITMAP的内容 Version:1.0 ...&lt;meta name=Generator content="Microsoft Excel"&gt; &lt;!--

    WebCam Capture VC++

    dlgFile.m_ofn.lpstrTitle = "Save Bitmap File Name"; if( dlgFile.DoModal() == IDCANCEL ) return; //---------------------------------------------------------------------------- CString ...

    MFC绘制直线

    1. **定义起点和终点**:首先确定直线的两个端点,例如(x1, y1)和(x2, y2)。 2. **计算步长**:根据两个端点的坐标,计算x方向和y方向的增量dx = x2 - x1和dy = y2 - y1。如果dx或dy为负值,可以取其绝对值,但需要...

Global site tag (gtag.js) - Google Analytics