Anti-Power 一个阻止屏幕自动关闭和屏保的工具

在需要长时间关注屏幕却又不想更改PC电源计划时,如观看在线视频、阅读文献资料,时间一长屏幕要不自动关闭,要不屏保自动启动,特别烦人。鄙人为此写解决这样问题的一个小工具,功能与keep display on类似,但提供了更方便的功能,如最小化为系统托盘,开机自动启动等,如下图所示:

关键代码有两点:
1. 禁用屏保

//定义API函数[DllImport("user32.dll")]
static extern bool SystemParametersInfo(uint uiAction, bool uiParam, ref bool pvParam, uint fWinIni);
const uint SPI_GETSCREENSAVEACTIVE = 0x0010;
const uint SPI_SETSCREENSAVEACTIVE = 0x0011;
const uint SPIF_SENDCHANGE = 0x0002;
const uint SPIF_SENDWININICHANGE = SPIF_SENDCHANGE;
//调用,其中函数内的false才是起作用的设置,active变量是在读取设置的时候使用的,这里没有实际意义。
bool active = false;
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, false, ref active, SPIF_SENDWININICHANGE);

SystemParametersinfo函数功能为查询或设置系统级参数,该函数也可以在设置参数中更新用户配置文件。
函数原型:B00L SystemParametersinfo(UINT uiAction,UINT uiParam,PVOID pvParam,UINT fWinlni);
详见:http://baike.baidu.com/view/1079845.htm
2. 阻止自动关闭屏幕

//定义API函数[DllImport("kernel32.dll")]
static extern uint SetThreadExecutionState(uint esFlags);
const uint ES_SYSTEM_REQUIRED = 0x00000001;
const uint ES_DISPLAY_REQUIRED = 0x00000002;
const uint ES_CONTINUOUS = 0x80000000;
//阻止自动关屏幕
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED);
//恢复自动关屏幕
SetThreadExecutionState(ES_CONTINUOUS);

SetThreadExecutionState用法和参数详见:http://msdn.microsoft.com/en-us/library/windows/desktop/aa373208(v=vs.85).aspx

如:ES_SYSTEM_REQUIRED 0×00000001
Forces the system to be in the working state by resetting the system idle timer.
强制系统处于工作状态,所以才不回自动关闭屏幕

3. 利用互斥使得程序单例执行

bool isRunning = true;
Mutex m = new Mutex(true, Application.ProductName, out isRunning);
if (isRunning)
 {
       Application.Run(new Form1()); ;
       m.ReleaseMutex();
 } else
 {
       MessageBox.Show("There is an instance running already!", "Single Instance Only", MessageBoxButtons.OK);
        return;
 }

Mutex的构造方法中有三个参数:
第一个参数:true,给调用线程赋予互斥体的初始所属权
第二个参数:互斥体的名称,我们用程序的名字
第三个参数:返回值,如果调用线程已被授予互斥体的初始所属权,则返回true
注意程序关闭释放互斥变量

下载地址:
点击此处下载 (适用于装有.net framework 2.0及以上版本的x86 32位windows 系统)

如需源代码,请联系作者索取 email: bjtuterry@bjtu.edu.cn

发表在 学习手记 | 标签为 , , | 留下评论

对《Maps of random walks on complex networks reveal community structure》 的阅读和评述

聚类算法,大多采用计算节点相似度或者相异度(距离)的方法进行聚类,而此类运算依赖于节点的属性,如二维几何平面上点的坐标.如果算法中存在比较频繁的计算相似度或者相异度,特别是在多属性或者属性迭代变化的情形下,由此引发的时间开销将是巨大的.Maps of random walks on complex networks reveal community structure文中提出的Infomap,基于节点链接关系随机游走以发现社区结构的方法,是一种链接关系上的概率模型聚类方法,这种方法无论在效率和聚类效果上都体现出明显的优越性.

(一)论文内容概要

  1. 阐明随机游走、压缩编码同社区发现的关系:通过随机游走对节点的访问频率,对节点和社区进行编码,力求最小化描述游走的平均编码长度的过程也即社区发现的过程;
  2. 说明如何在上述方式的随机游走和压缩编码过程中发现社区结构;
  3. 对比本文提出的发现社区的方法和传统的优化模块性方法;
  4. 描述了在自然科学和社会科学两方面的论文引用网络上进行的一个实际实验.

(二)论文核心思想和社区发现算法过程

链接关系反应了节点间关系的亲疏程度,随机游走即为在节点和链接关系组成的网络中,从一个节点出发,按照链接关系依次遍历访问其他节点的过程,如图1(A)所示.如果对每个节点进行唯一命名(编码),那么就可以如图1(B)所示描述随机游走的过程.所以,如何压缩描述随机游走过程的编码长度,关键在于节点的命名方式.显然地,等长编码是不可取的.另一方面,根据Shannon理论,可以将编码长度压缩到接近理论极限值,但是,压缩编码不是文章的唯一目的;同样地,直观上Huffman编码是一种可取的编码方法,利用随机游走过程中每个节点被遍历访问的频率进行Huffman编码,这种方式确实能够压缩编码,但是,Infomap关注的不是如何去为节点编码,而是描述随机游走过程的编码的理论极限压缩程度,同时怎样在这个过程中呈现出社区结构,即聚类的簇.
根据Shannon定理,如果使用n个码字来描述随机变量Xn个状态,且每个状态出现的频率为p(i),那么描述的平均码长不会超过X的熵:

为了在压缩最小平均编码过程中,呈现出社区结构,Infomap提出分两级描述随机游走过程的编码方式.假定已经存在特定的社区结构,那么随机游走过程中,节点驻留在某个社区(簇)的频率是易知的,同理,从一个社区中跳转到其他社区的概率也是易知的,据此,首先对存在的每个社区进行Huffman编码,即经常发生跳转的社区编码长度短,而游走在其内部驻留机率大的社区编码长度长;同理对每个社区内部的节点根据访问频率也进行Huffman编码,因为每个社区也存在编码,所以两个不同社区中的节点编码是可以存在相同编码的,即社区0中的11节点明显区别与社区10中的节点中的11.于是,单个节点的平均编码长度明显小于对网上中所有节点进行1级Huffman编码的平均长度.并且,Infomap在此种编码方式下描述随机游走过程,只需要在跳出一个社区和转入一个社区的时候在编码中加入社区编码(如图1(C)、图1(D)所示),这样边大大压缩了编码长度.由此可见,发现社区结构过程和压缩随机游走平均编码长度过程是对偶的.
实际算法中,Infomap并不对每个节点编码,也不进行随机游走,而是根据信息熵的理论,求出其提出的编码方式的理论极限最小平均编码长度.于是,Infomap提出了其聚类指标MapEquation[6]:
式(2)中红色部分社区(簇)间游走所需的最小平均编码长度,蓝色部分为在社区内部游走所需的最小平均编码长度,故L(M)为无限步随机游走过程中,Infomap编码方式的理论极限最小平均编码长度.在原文的SI(Supporting Information)中详细地阐述了式(2)的计算方法,由于本文只阐述Infomap的算法思想,仅列出公式,不再赘述.

从式(3)(4)(5)可以看出,L(M)的值依赖于.在的计算式(4)中,τ为一个随机因子,即随机游走可以在τ的概率下随机的跳转到任何一个节点,这避免了随机游走被局限于某个社区(簇)内部的情况,特别当网络是有向的时候,τ存在的意义显得尤为明显,一般情况下,τ取值与Google Page Rank算法一致,令τ=0.15;ni是当前社区的节点数,n为总的节点数,wαβ为当前社区内部一个节点α由链接访问社区外节点β的权重.各式均依赖的 ,为节点在随机游走过程被访问到的频率,实际算法中,不可能通过实现无限步游走来得到对拥有n个节点的随机游走过程,可以看作是拥有n个状态空间的不可约遍历性马尔科夫链,根据Preeon-Frobineous理论,不可约的、遍历性的马尔科夫链拥有一个唯一的平稳状态.为求得每个节点的遍历性访问频率,从网络节点的初始分布开始,即=1/n,由幂法(Power Method)[4]可以求得该马尔科夫链的平稳分布,即为节点的访问频率.关于幂法(Power Method)可以从此web资源获得理论支持.

图1. 压缩网络信息流的描述长度以发现社区结构

利用MapEquation进行社区发现的算法(Infomap)流程如下:

  1. 首先,由幂法(power method)计算随机游走过程中每个节点的访问频率,需要注意的是,在迭代过程中,合并得到的社区也称之为一个节点;
  2. 其次,用确定的贪心算法求解所有可能网络划分下的解空间;
  3. 最后,用模拟退火过程,优化得到最后的社区发现结果.

对应于传统优化模块性函数的社区发现方法中的Q函数,其一般描述如下:

Infomap算法过程类似于传统的优化模块性函数的社区发现方法,以每个节点都为一个社区(簇)开始,逐步合并使得L(M)减少最多的两个社区(优化模块性函数法则合并使得Q函数值增大最多的两个社区),直到合并社区使得L(M)变化很细微时算法停止,这个过程的得到的解空间中存在一个使得L(M)最小的解,这个解对应的社区划分即为所求的社区结构.随机游走仅仅是形象意义上的一个概念,有助于理解社区发现和压缩随机游走过程平均编码长度的对偶性;在实际的算法实现中,使用幂法(power method)计算在无限步随机游走过程中的各个节点被访问频率.

(三)优缺点概述

优点:

  1. 社区发现速度快,准确率高;不需要预设社区数等传统方法的运行参数;大规模网络社区发现更具优势;
  2. 游走的过程恰好反应了网络中节点间内在的相互作用和关系紧密程度,比起单纯靠出入度衡量的模块性函数来说,更具实际意义.
  3. 信息图模型,也即最小化随机游走平均编码长度模型在无监督学习中是一种新的聚类方法.在这个模型基础上,作者相继在2010年发表了Mapping change in large networksTime walkers and spatial dynamics of ageing information ,并于2011年4月最后修订了层次社区发现的文章Multilevel compression of random walks on networks reveals hierarchical organization in large integrated systems [2].信息图模型表现出越来越明显的生命力和吸引力.

缺点或不足:

1. 不适用于某些特殊的有向网络,这些网络中,因为有向,往往游走过程不能畅通,随机游走的过程受到限制, 即随机游走不能通过链接的方式跳转到其他社区,只能靠一定概率下()的随机访问,才能够进行社区间的游走过程.这些网络中(如图2)优化模块性方法更有优势.

图2. 随机游走受阻示意图

2. 由Community detection algorithms: a comparative analysis[3]一文中的对比实验可以看出,虽然Infomap在绝大多数社区结构较为明显的网络中,聚类效果很好,但是当网络结构趋向不明显时,聚类效果急剧下降,如图3所示.

(A)
(B)
图3. 不同网络结构性算法准确度(NMI)对比.A为纯拓扑结构网络中,μt随着变化的算法准确度对比;B为带权网络中,固定两个μt,随着μw变化的算法准确度对比.μt为社区间的度数参数,μw为带权网络中社区间的权重参数,这两个参数值越大,说明社区间的度数和边权重越大,社区结构越不明显,聚类越困难;N为节点个数,S和B代表网中社区内部的节点数的多少,S指社区大小为10-50个节点,B指社区大小为20-100个节点.

3. 社会网络中的节点和大多都包含了丰富的属性信息(不止一条属性或者一个边权值),算法中并没有考虑这些属性对游走的影响.事实上,如果把节点属性和边属性融合做为游走路径选择的一个指标,或许会有更高的准确率.

参考文献

[1] Martin Rosvall, Carl T. Bergstrom. Maps of random walks on complex networks reveal community structure. PNAS(January 29, 2008), vol. 105, no. 4, 1123.
[2] Martin Rosvall, Carl T. Multilevel compression of random walks on networks reveals hierarchical organization in large integrated systems.
[3] Andrea Lancichinetti, Santo Fortunato1. Community detection algorithms: a comparative analysis.
[4] Power method: http://math.fullerton.edu/mathews/n2003/PowerMethodMod.html.
[5] InfoMap Web Pages: http://www.tp.umu.se/~rosvall/
[6] Martin Rosvall, Carl T. The map equation.


发表在 学习手记 | 标签为 , | 留下评论

表达式求值

1. 逆波兰式

2. W3EVAL

http://www.ibm.com/developerworks/cn/java/j-w3eva/

MathematicalExpression.java
 
import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
 
/**
* MathematicalExpression 基于逆波兰式,即数学表达式的后缀表示,
* 对指定表达式进行求
* 值。暂时支持简单的二元运算
* @author Terry
* @version 2010-8-30
*/
public class MathematicalExpression {
     private String expression = "";
     private List postExp = new ArrayList();
/**
*
* @param expression
*/
public MathematicalExpression(String expression) {
      this.expression = expression;
}
public MathematicalExpression(){};public String getExpression() {
      return expression;
}
public void setExpression(String expression) {
     this.expression = expression;
}
/**
* 得到表达式的值
* @return
*/
public double getValue() {
    toPostExpression();
   Stack stack = new Stack();
 
   double n1, n2, result;
for(String element : postExp) {
    if (isOperator(element)) {
    n1 = Double.parseDouble(stack.pop());
    n2 = Double.parseDouble(stack.pop());
    result = doOperate(n2, n1, element);
     stack.push(new Double(result).toString());
   } else {
     stack.push(element);
  }
}
return Double.parseDouble(stack.pop());
}
private void toPostExpression(){
    expression += "#";
    char ch = '#', ch1, op;
    Stack s = new Stack();
    StreamTokenizer tf = new StreamTokenizer(new StringReader(expression));
    tf.ordinaryChar('/');
    tf.ordinaryChar('(');
    tf.ordinaryChar(')');
    tf.ordinaryChar('-');
    s.push(ch);
    int i;
    try {
        i = tf.nextToken();
        while (i != StreamTokenizer.TT_EOF && !s.isEmpty()) {
        switch (i) {
            case StreamTokenizer.TT_EOF:
            case StreamTokenizer.TT_EOL:
                break;
            case StreamTokenizer.TT_NUMBER:
                postExp.add(String.valueOf(tf.nval));
                i = tf.nextToken();
                break;
            case StreamTokenizer.TT_WORD:
                break;
            default:
                ch = (char) i;
                ch1 = s.peek();
                if (isp(ch1) < icp(ch)) {
                    s.push(ch);
                    i = tf.nextToken();
                } else if (isp(ch1) > icp(ch)) {
                    op = s.pop();
                    postExp.add(String.valueOf(op));
                } else {
                    op = s.pop();
                    if (op == '(')
                    i = tf.nextToken();
                }
        }
    }
    } catch (IOException e) {
    // TODO Auto-generated catch block
    //e.printStackTrace();
    }
}
 
//实际运算
private  double doOperate(double n1, double n2, String operator) {
	if (operator.equals("+"))
		return n1 + n2;
	else if (operator.equals("-"))
		return n1 - n2;
	else if (operator.equals("*"))
		return n1 * n2;
	else
		return n1 / n2;
}
//判断是否是操作符
private static boolean isOperator(String str){
    return str.equals("+") || str.equals("-") || str.equals("*")
             || str.equals("/");
}
 
// 栈内优先级
private  short isp(char c) {
	short priority = 0;
	switch (c) {
	case '#':
		priority = 0;
		break;
	case '(':
		priority = 1;
		break;
	case '*':
	case '/':
		priority = 5;
		break;
	case '+':
	case '-':
		priority = 3;
		break;
	case ')':
		priority = 6;
		break;
	default:
		break;
	}
	return priority;
}
 
// 栈外优先级
private  short icp(char c) {
	short priority = 0;
	switch (c) {
	case '#':
		priority = 0;
		break;
	case '(':
		priority = 6;
		break;
	case '*':
	case '/':
		priority = 4;
		break;
	case '+':
	case '-':
		priority = 2;
		break;
	case ')':
		priority = 1;
		break;
	default:
		break;
	}
	return priority;
}

测试代码:

public static void main(String[] args) {
     Scanner scanner = new Scanner(System.in);
     DecimalFormat df=new DecimalFormat("0.00");
     MathematicalExpression me = new MathematicalExpression();
     while(scanner.hasNext())
     {
         me.setExpression(scanner.next());
          System.out.println(df.format(me.getValue()));
     }
 }

 

发表在 备忘录 | 标签为 | 留下评论

http://code.msdn.microsoft.com/wpfsamples

http://code.msdn.microsoft.com/wpfsamples

发表在 备忘录 | 一条评论

利用ClassFactory动态更新ItemRender

本人在动态更新Flex LineChart 的LineSeries的itemRender的时候遇到了问题。

在用mxml标签的时候很容易按如下方式制定DataPoint的样式,即ItemRender:

<mx:LineSeries yField=”Profit” form=”curve” displayName=”Profit” itemRenderer=”mx.charts.renderers.CircleItemRenderer”/>

但是当我在As代码中想动态的更改的时候却遇到了问题,不仅无法改变其样式,反而影响了其他组件的初始化。本人尝试过

line.setStyle(“itemRender”, new mx.charts.renderers.CircleItemRenderer());

line.setStyle(“itemRender”, “mx.charts.renderers.CircleItemRenderer”);

均不成功。

经google ,需要用如下方式方能实现:

line.setStyle(“itemRender”, new mx.core.ClassFactory(CircleItemRenderer));

具体原因,待学习。

发表在 学习手记 | 标签为 | 3 条评论

QT Ecplise qDebug

Qt程序打印一些命令行调试信息一般使用qWarning和qDebug函数, 在Linux平台下, 这两个函数分别向标准错误和标准输入打印默认都是会显示在控制台上, 但Windows平台就不同了。 默认情况下Qt Windows程序是看不到这些信息的, 这给我们编程和调试带来一些不便。 解决的方法其实非常简单, 一句话就可以搞定:

在pro文件里加入

CONFIG+=console

然后需要用qmake重新生成Makefile并且make clean再make即生效。

发表在 备忘录 | 标签为 , | 一条评论

[转载]寻找凸包的Graham 扫描法

1,点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内。
2,凸包最常用的凸包算法是Graham扫描法和Jarvis步进法。
3,Graham扫描法:
首先,找到所有点中最左边的(y坐标最小的),如果y坐标相同,找x坐标最小的.
以这个点为基准求所有点的极角(atan2(y-y0,x-x0)),并按照极角对这些点排序,前述基准点在最前面,设这些点为P[0]..P[n-1.
注:这样预处理后,保证p[0],p[1]和p[n-1]都是凸包上的点.
建立一个栈,初始时P[0]、P[1]、P[2]进栈,对于 P[3..n-1]的每个点,若栈顶的两个点与它不构成”向左转”的关系,则将栈顶的点出栈,直至没有点需要出栈以后将当前点进栈;
所有点处理完之后栈中保存的点就是凸包了。

图示:

4,实现代码

Cpp代码
  1. #include <iostream>
  2. #include <cmath>
  3. using namespace std;
  4. /*
  5. PointSet[]:输入的点集
  6. ch[]:输出的凸包上的点集,按照逆时针方向排列
  7. n:PointSet中的点的数目
  8. len:输出的凸包上的点的个数
  9. */
  10. struct Point
  11. {
  12. float x,y;
  13. };
  14. //小于0,说明向量p0p1的极角大于p0p2的极角
  15. float multiply(Point p1,Point p2,Point p0)
  16. {
  17. return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
  18. }
  19. float dis(Point p1,Point p2)
  20. {
  21. return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
  22. }
  23. void Graham_scan(Point PointSet[],Point ch[],int n,int &len)
  24. {
  25. int i,j,k=0,top=2;
  26. Point tmp;
  27. //找到最下且偏左的那个点
  28. for(i=1;i<n;i++)
  29. if ((PointSet[i].y<PointSet[k].y)||((PointSet[i].y==PointSet[k].y)&&(PointSet[i].x<PointSet[k].x)))
  30. k=i;
  31. //将这个点指定为PointSet[0]
  32. tmp=PointSet[0];
  33. PointSet[0]=PointSet[k];
  34. PointSet[k]=tmp;
  35. //按极角从小到大,距离偏短进行排序
  36. for (i=1;i<n-1;i++)
  37. {
  38. k=i;
  39. for (j=i+1;j<n;j++)
  40. if( (multiply(PointSet[j],PointSet[k],PointSet[0])>0)
  41. ||((multiply(PointSet[j],PointSet[k],PointSet[0])==0)
  42. &&(dis(PointSet[0],PointSet[j])<dis(PointSet[0],PointSet[k]))) )
  43. k=j;//k保存极角最小的那个点,或者相同距离原点最近
  44. tmp=PointSet[i];
  45. PointSet[i]=PointSet[k];
  46. PointSet[k]=tmp;
  47. }
  48. //第三个点先入栈
  49. ch[0]=PointSet[0];
  50. ch[1]=PointSet[1];
  51. ch[2]=PointSet[2];
  52. //判断与其余所有点的关系
  53. for (i=3;i<n;i++)
  54. {
  55. //不满足向左转的关系,栈顶元素出栈
  56. while(multiply(PointSet[i],ch[top],ch[top-1])>=0) top–;
  57. //当前点与栈内所有点满足向左关系,因此入栈.
  58. ch[++top]=PointSet[i];
  59. }
  60. len=top+1;
  61. }
  62. const int maxN=1000;
  63. Point PointSet[maxN];
  64. Point ch[maxN];
  65. int n;
  66. int len;
  67. int main()
  68. {
  69. int n=5;
  70. float x[]={0,3,4,2,1};
  71. float y[]={0,0,0,3,1};
  72. for(int i=0;i<n;i++)
  73. {
  74. PointSet[i].x=x[i];
  75. PointSet[i].y=y[i];
  76. }
  77. Graham_scan(PointSet,ch,n,len);
  78. for(int i=0;i<len;i++)
  79. cout<<ch[i].x<<” ”<<ch[i].y<<endl;
  80. return 0;
  81. }
#include <iostream>
#include <cmath>
using namespace std;
 
/*
PointSet[]:输入的点集
ch[]:输出的凸包上的点集,按照逆时针方向排列
n:PointSet中的点的数目
len:输出的凸包上的点的个数
*/
 
struct Point
{
    float x,y;
};
 
//小于0,说明向量p0p1的极角大于p0p2的极角
float multiply(Point p1,Point p2,Point p0)
{
    return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
}
 
float dis(Point p1,Point p2)
{
    return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
}
 
void Graham_scan(Point PointSet[],Point ch[],int n,int &amp;len)
{
    int i,j,k=0,top=2;
    Point tmp;
 
    //找到最下且偏左的那个点
    for(i=1;i<n;i++)
        if ((PointSet[i].y&lt;PointSet[k].y)||((PointSet[i].y==PointSet[k].y)
               &amp;&amp;(PointSet[i].x&lt;PointSet[k].x)))
            k=i;
    //将这个点指定为PointSet[0]
    tmp=PointSet[0];
    PointSet[0]=PointSet[k];
    PointSet[k]=tmp;
 
    //按极角从小到大,距离偏短进行排序
    for (i=1;<n-1;i++)
    {
        k=i;
        for (j=i+1;j<n;j++)
            if( (multiply(PointSet[j],PointSet[k],PointSet[0])&gt;0)
                ||((multiply(PointSet[j],PointSet[k],PointSet[0])==0)
                    &amp;&amp;(dis(PointSet[0],PointSet[j])&lt;dis(PointSet[0],
                       PointSet[k]))) )
                k=j;//k保存极角最小的那个点,或者相同距离原点最近
        tmp=PointSet[i];
        PointSet[i]=PointSet[k];
        PointSet[k]=tmp;
    }
    //第三个点先入栈
    ch[0]=PointSet[0];
    ch[1]=PointSet[1];
    ch[2]=PointSet[2];
    //判断与其余所有点的关系
    for (i=3;i&lt;n;i++)
    {
        //不满足向左转的关系,栈顶元素出栈
        while(multiply(PointSet[i],ch[top],ch[top-1])&gt;=0) top--;
        //当前点与栈内所有点满足向左关系,因此入栈.
        ch[++top]=PointSet[i];
    }
    len=top+1;
}
 
const int maxN=1000;
Point PointSet[maxN];
Point ch[maxN];
int n;
int len;
 
int main()
{
    int n=5;
    float x[]={0,3,4,2,1};
    float y[]={0,0,0,3,1};
    for(int i=0;i<n;i++)
    {
        PointSet[i].x=x[i];
        PointSet[i].y=y[i];
    }
    Graham_scan(PointSet,ch,n,len);
    for(int i=0;i&lt;len;i++)
        cout<<ch[i].x<<" "&<<ch[i].y<<endl;
    return 0;
}

5,应用:http://acm.pku.edu.cn/JudgeOnline/problem?id=1113
实现代码:

Cpp代码
  1. #include <iostream>
  2. #include <cmath>
  3. using namespace std;
  4. /*
  5. PointSet[]:输入的点集
  6. ch[]:输出的凸包上的点集,按照逆时针方向排列
  7. n:PointSet中的点的数目
  8. len:输出的凸包上的点的个数
  9. */
  10. struct Point
  11. {
  12. float x,y;
  13. };
  14. //小于0,说明向量p0p1的极角大于p0p2的极角
  15. float multiply(Point p1,Point p2,Point p0)
  16. {
  17. return((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
  18. }
  19. float dis(Point p1,Point p2)
  20. {
  21. return(sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
  22. }
  23. void Graham_scan(Point PointSet[],Point ch[],int n,int &len)
  24. {
  25. int i,j,k=0,top=2;
  26. Point tmp;
  27. //找到最下且偏左的那个点
  28. for(i=1;i<n;i++)
  29. if ((PointSet[i].y<PointSet[k].y)||((PointSet[i].y==PointSet[k].y)&&(PointSet[i].x<PointSet[k].x)))
  30. k=i;
  31. //将这个点指定为PointSet[0]
  32. tmp=PointSet[0];
  33. PointSet[0]=PointSet[k];
  34. PointSet[k]=tmp;
  35. //按极角从小到大,距离偏短进行排序
  36. for (i=1;i<n-1;i++)
  37. {
  38. k=i;
  39. for (j=i+1;j<n;j++)
  40. if( (multiply(PointSet[j],PointSet[k],PointSet[0])>0)
  41. ||((multiply(PointSet[j],PointSet[k],PointSet[0])==0)
  42. &&(dis(PointSet[0],PointSet[j])<dis(PointSet[0],PointSet[k]))) )
  43. k=j;//k保存极角最小的那个点,或者相同距离原点最近
  44. tmp=PointSet[i];
  45. PointSet[i]=PointSet[k];
  46. PointSet[k]=tmp;
  47. }
  48. //第三个点先入栈
  49. ch[0]=PointSet[0];
  50. ch[1]=PointSet[1];
  51. ch[2]=PointSet[2];
  52. //判断与其余所有点的关系
  53. for (i=3;i<n;i++)
  54. {
  55. //不满足向左转的关系,栈顶元素出栈
  56. while(multiply(PointSet[i],ch[top],ch[top-1])>=0) top–;
  57. //当前点与栈内所有点满足向左关系,因此入栈.
  58. ch[++top]=PointSet[i];
  59. }
  60. len=top+1;
  61. }
  62. const int maxN=1010;
  63. Point PointSet[maxN];
  64. Point ch[maxN];
  65. int n;
  66. int len;
  67. int main()
  68. {
  69. double ans=0;
  70. int d;
  71. cin>>n>>d;
  72. for(int i=0;i<n;i++)
  73. cin>>PointSet[i].x>>PointSet[i].y;//input the data;
  74. Graham_scan(PointSet,ch,n,len);
  75. for(int i=0;i<len;i++)
  76. ans+=dis(ch[i],ch[(i+1)%len]);
  77. ans+=2*d*acos(-1.0); //等价于圆形周长
  78. cout<<(int)(ans+0.5)<<endl; //四舍五入
  79. return 0;
  80. }

[source]: http://kmplayer.javaeye.com/blog/604405

发表在 备忘录 | 标签为 , , | 留下评论

Display remote applications on my local X server in Linux

Display remote applications on my local X server in Linux

by Vivek Gite · 8 comments

By default Linux disallows TCP connections from remote hosts. It prevents applications from running on a remote host and being able to be displayed on the local x server.

To enable the X server to display remote applications open /usr/share/gdm/defaults.conf file. Set DisallowTCP=true to false

# vi /usr/share/gdm/defaults.conf
Set DisallowTCP=true to false
DisallowTCP=false

Setting DisallowTCP to false will allow remote clients to connect.

If you don’t know exact location of GDM defaults.conf conf file use find command
find / -name “defaults.conf”

Now restart GNOME aka GDM.
# reboot
OR
# init 3
# init 5

How do I test new setup?

Type any one of the following command on the client
xhost remote-ip
xhost remotehost
xhost remote.server.com

Now SSH into the remote client and type any one of the command:
xeyes -display remote-ip:0
xeyes -display remotehost:0
xeyes -display remoteserver.com:0

xeyes should popup on client system. Enjoy!

source:http://www.cyberciti.biz/tips/how-to-display-remote-applications-on-my-local-linux-x-server.html

发表在 备忘录 | 标签为 | 一条评论

Flex的一些学习资源

我用的IDE是Flex Builder3, 实际上Adobe提供的最新IDE是Flash Builder4 Beta,Flex3和Flex4的本质上没有什么区别,只是在

定义控件样式和皮肤的时候把样式和皮肤的概念变得更独立,对于不熟悉的人我觉得反而在理解上不直观,但是代码变得十分清晰

、有条理,同时把Flex3中的不足完善了;还有一点是,上面提到的两款IDE都是收费的,但是Flex3的序列号网上很多,Flex4的不

是很好破解,对我们常用的Flex Chart组件来说更是有限制,对于个人用户开发产品来说建议使用Flex Builder3。

一些学习Flex的网址:
1. Flex官方教学视频  http://www.riameeting.com/riavideo
2. 一个很棒的Flex开源库(项目中有用到其中的一个) http://code.google.com/p/flexlib/wiki/ComponentList
3. 另外的Flex开源库列表,有兴趣可以看一下 http://www.javaeye.com/topic/508245
4. 国内很有名的社区JavaEye,不仅可以学习Flex,囊括了Java等等很多技术,是一个比较活跃的社区,挺有用

http://www.javaeye.com 其中的Flex半空:http://www.javaeye.com/forums/tag/Flex
5. 一个充满了Flex例子的博客 http://blog.flexexamples.com/ 同样一个中文版的博客 http://blog.minidx.com/
6. 一个Flex学习论坛 http://bbs.airia.cn/FLEX/list-1.aspx 其中很有价值的一片文章http://bbs.airia.cn/FLEX/thread2768-1-1.aspx
7. Tour de Flex一共包含200个样例,每个样例均包含源代码。它们包括Flex核心组件,FLEX数据存取、AIR桌面应用,API ,数

据可视化,地图,以及自定义组件,效果,外观等。下载地址:

http://download.macromedia.com/pub/developer/air/TourDeFlex.air
.air格式的文件的安装,需要Adobe Air环境,所以请先下载

http://219.239.26.6/download/3435819/4464147/2/exe/70/112/1266538130246_624/AdobeAIRInstaller.exe 安装,再进行其他

的.air程序的安装
我把我尽量能提供的资料都发给你们,但是有些由于附件太大,所以给出网址,所以请自行下载!

发表在 学习手记 | 标签为 | 2 条评论

模式学习之Null Object

模式学习之Null Object

背景:要从数据库中得到一个名叫Bob的员工(Employee),如果今天是其薪酬支付日期(isTimeToPay()),即为之支付薪酬(pay())。

对于长期进行C-Based语言开发的人,简单来说,代码大致如下:

Employee e = DB.getEmployee(“Bob”);
 
if(e != null &amp;&amp; e.isTimeToPay()){
 
      e.pay();
 
}

这样的代码对我们长期写C-Based语言代码的人已经司空见惯,&&首在第一个表达式值为true的时候,才会执行第二个表达式。当然在也许会有人这样写:

Employee e = DB.getEmployee(“Bob”);
 
try{
 
    if(e.isTimeToPay())
 
    {
 
        e.pay();
 
    }
 
}catch(NullPointerException e){
 
    e.printStackTrace();
 
}

这两种写法本质上都没有什么错,但是都是及其繁琐的,对于经验不足的程序员,在大多时候都会忘记对e做是否为空的检查,导致异常抛出。

引入Null Object模式,即可很好的解决这个问题,即不需要对e是否为null值做检验,直接使用,不仅代码美观易懂,也排除了很多可能潜在的错误。

下面演示Null Object的魅力:

首先,建立Employee接口,如下:

import java.util.Date;
 
public interface Employee {
    public boolean isTimeToPay(Date payDate);
 
    public void pay();
 
     public static Employee NULL = new Employee() {
 
         @Override
 
         public void pay() {
 
        }
 
        @Override
 
         public boolean isTimeToPay(Date payDate) {
 
             return false;
 
        }
 
    };
 
}

该接口有一个名为NULL的静态变量持有一个匿名的Employee实体,这个匿名的实现体是无效雇员(null employee)类的唯一实例。其中isTimeToPay()返回false,而pay(0方法实现为空。

对于DB类,我们直接返回一个Employee.NULL ,以便测试:

public class DB {
 
    //为了测试,这里我们直接返回Employee.NULL
 
     public static Employee getEmployee(String name){
 
    //return null;
 
     return Employee.<em>NULL</em>;
 
    }
 
}

在JUnit下写出我们的测试方法:

public class TestEmployee {
 
    @Test
 
     public void testNullObject() throws Exception
 
    {
 
        Employee e = DB.<em>getEmployee</em>("Bob");
 
         if(e.isTimeToPay(new Date())){
 
            e.pay();
 
        }
 
         assertEquals(Employee.NULL, e);
 
    }
 
    @Test
 
     public void testCBased() throws Exception
 
    {
 
         Employee e = DB.<em>getEmployee</em>("Bob");
 
         if(e != null &amp;&amp; e.isTimeToPay(new Date())){
 
         e.pay();
 
    }
 
         assertEquals(null, e);
 
    }
 
    @Test
 
     public void testNoCheck() throws Exception
 
    {
 
    Employee e = DB.<em>getEmployee</em>("Bob");
 
     if(e.isTimeToPay(new Date())){
 
        e.pay();
 
    }
 
        assertEquals(null, e);
 
    }
 
}

可见,使用Null Object不仅减少了代码上重复的检查对象是否为空,甚至直接排斥了那些没有良好参数检查习惯的编程人员可能会犯的错。使无效雇员类成为一个匿名类是一种确保该类只有一个实例的方法,实际上并不存在NullEmployee本身。任何其他的人都无法创建无效雇员类的其他实例。这样的话,才需要的场合我们可以使用如下表达式:

if(e == Emplyee.NULL)

如果可以创建无效雇员类的多个实例,那么以上表达式就是非常不可靠的。

长期使用C-Based语言的人习惯了返回null或者0或者-1,这样的函数返回值在使用前是必须经过检查的。NULL OBJECT模式改变了这一点。使用该模式,我们可以确保函数返回的总是有效对象,其实在他们失败时也是如此,因为这些代表失败的对象“什么也不做”。

参考:《Agile Software Development -Principles, Patterns, Practices》

发表在 学习手记 | 标签为 | 留下评论