HOMEWORK-03

红字部分为组员修改的意见

文件介绍

在EXE文件夹中的main.exe文件为本项目执行文件直接点击即可,CODE文件夹中的C文件夹中包含了算法部分的代码,其编译出的DLL文件在bin文件夹中,另外在CODE文件夹下的python文件为本项目GUI实现,其样本XML在UI文件夹中。

项目回顾

对于HOMEWORK-02,-a的模式进行了改进,(HOMEWORK-02参见链接
)由于图的规模不容易控制(如果是正负间隔的数据情况则无法使用并查集缩点):

样例1:

4 4

1 -2 3 -4

-5 6 -7 8

9 -10 11 -12

-13 14 -15 16

所以在这里我认为很难有一个合适的算法进行-a的操作,我选择使用SAA退火算法,退火时MaxS表示当前状态下选择的最优状态,而RanS表示随意扩展的一个状态,比较这两个状态来判断是否应该选取局部优解,而在大多数情况下该退火算法会得到最优解:

SAA

void SAA(int
v,float T,float r,float Tmin)

{

int
i,max,maxS=0,ranS,tmp,SMR,sum,ri,j;//State

struct link
* p;

srand(time(0));

sum=value[v];

for(i=0;i<1024;i++){visited[i]=0;available[i]=0;}

topq=0;p=g[v];visited[v]=1;

while
(p!=NULL)

{

if
(!visited[p->t]){available[p->t]=1;}

p=p->next;

}

while(1)

{

max=-10000000;

ri=0;

for
(i=0;i<num;i++)

{

if
(visited[i]) {continue;}

if
(available[i])

{

tmp=estimate(i);

if (tmp>max)

{

max=tmp;

maxS=i;

}

ri++;

}

}

if
(ri==0) {break;}

ranS=rand()%ri+1;

for
(i=0;i<num;i++)

{

if
(available[i]&&!visited[i])

{

ranS--;

if (ranS==0)

{

ranS=i;

break;

}

}

}

if
(visited[ranS]||!available[ranS]) {return ;}

SMR=0;

tmp=estimate(maxS);

if
(sum+tmp>totalmax) {totalmax=sum+tmp;pseudoexpand(maxS);}

if
(tmp>0){SMR=1;}

else

{

if
(exp(tmp/T)>(rand()%10000)/10000.0){SMR=1;}

}

T*=r;

tmp=SMR==1?estimate(maxS)-estimate(ranS):estimate(ranS);

if
(sum+estimate(ranS)>totalmax)
{totalmax=sum+estimate(ranS);pseudoexpand(ranS);}

if
(exp(tmp/T)>(rand()%10000)/10000.0){SMR=2;}

T*=r;

switch(SMR)

{

case 1:sum+=expand(maxS);break;

case 2:sum+=expand(ranS);break;

}

if
(T<Tmin){break;}

if
(sum>totalmax) {totalmax=sum;printf("%d\n",totalmax);for
(j=0;j<1024;j++){chosen[j]=visited[j];}}

}

}

退火算法详情参见链接
通过五次相同的退火过程,在每次退火过程中设置1000*V(V表示点数)次初始温度,得到一个相当优的解,其很大程度上就是最优解。 然后对于这个较优解继续进行比较简单的提升通过patch()函数。

patch

void patch()

{

int
i,j,sum,yes;

struct link
* p,*q;

while(1)

{

yes =
0;

for
(i=0;i<num;i++)

{

if
(value[i]>0&&!chosen[i])

{

for (j=0;j<1024;j++) {visited[j]=0;}

q = DFS(i);

p = q;

if (p==NULL)

{

continue;

}

sum = p->s;

if (sum>=0)

{

yes = 1;

while (q!=NULL)

{

chosen[q->t] =
1;

q = q->next;

}

}

}

}

if
(yes==0) {break;}

}

}

struct link *
DFS(int v)

{

struct link
* p;

struct link
* q;

struct link
* tmp;

int
result=-100000;

p = g[v];

visited[v]
= 1;

q = (struct
link *)malloc(sizeof(struct link));

q->next
= NULL;q->s = value[v];q->t = v;

while
(p!=NULL)

{

//printf("%d %d
%d\n",p->t,visited[p->t],chosen[p->t]);

if
(chosen[p->t])

{

visited[v] = 0;

q->next = NULL;q->s = value[v];q->t = v;

return q;

}

if
(visited[p->t]||value[p->t]>0)

{

p=p->next;

continue;

}

if
(value[p->t]<0&&!chosen[p->t])

{

tmp
= DFS(p->t);

if
(tmp!=NULL&&result<tmp->s+value[v])

{

result = tmp->s+value[v];

q->next = tmp;

q->s=tmp->s+value[v];

}

}

p =
p->next;

}

visited[v]
= 0;

if
(q->next!=NULL) return q;

return
NULL;

}

将其余有正收益的点不断选取,得到最后的一个局部不可扩充的最优解。 本算法基于时间上的考虑进行了一部分取舍,首先理想情况下应该是通过patch()操作之后得到状态RanS与MaxS,其次patch无法对以下情况进行扩充,以下的情况必须由SAA在退火过程中选取:

样例2:

3 3

4 -100 100

-5 100 100

4 -100 100

两个价值为4的点都无法被patch(),但由于规模小可以在SAA的过程中被挑选出来,于是仍能得到最优解。 另外-v -h参数对-a参数来说只是建图的方式有所不同。

setgraph:

void
setgraph(int vertical,int horizontal)

{

int
i1,j1,i,j,yes;

struct link
* p;

num=0;

for
(i=0;i<n;i++){for (j=0;j<m;j++){father[i][j]=i*m+j;}}

for
(i=0;i<n;i++)

{

for
(j=0;j<m;j++)

{

h[i][j]=0;

father2g[i*m+j]=-1;

if
(a[i*m+j]>=0)

{

if
(i>0&&a[(i-1)*m+j]>=0){father[fatherfind(i,j)/m][fatherfind(i,j)%m]=father[fatherfind(i-1,j)/m][fatherfind(i-1,j)%m];}

if
(i==0&&a[(n-1)*m+j]>=0&&vertical){father[fatherfind(i,j)/m][fatherfind(i,j)%m]=father[fatherfind(n-1,j)/m][fatherfind(n-1,j)%m       ];}

if (j>0&&a[i*m+j-1]>=0){father[fatherfind(i,j)/m][fatherfind(i,j)%m]=father[fatherfind(i,j-1)/m][fatherfind(i,j-1)%m];}

if
(j==0&&a[i*m+m-1]>=0&&horizontal){father[fatherfind(i,j)/m][fatherfind(i,j)%m]=father[fatherfind(i,m-1)/m][fatherfind(i,m-1)%m       ];}

}

}

}

for
(i=0;i<n;i++)

{

for
(j=0;j<m;j++)

{

if
(a[i*m+j]>0)

{

if (father2g[fatherfind(i,j)]==-1)

{

father2g[fatherfind(i,j)]=num;

value[num]=a[i*m+j];

g[num]=NULL;

num++;

}

else{value[father2g[fatherfind(i,j)]]+=a[i*m+j];}

}

else

{

value[num]=a[i*m+j];

father2g[i*m+j]=num;

g[num]=NULL;

num++;

}

}

}

for
(i=0;i<n;i++)

{

for
(j=0;j<m;j++)

{

for
(shifter=0;shifter<4;shifter++)

{

i1=i+shifti[shifter];

j1=j+shiftj[shifter];

if (i1<0||i1>=n)

{

if (vertical) {i1=(i1+n)%n;}

else {continue;}

}

if (j1<0||j1>=m)

{

if (horizontal) {j1=(j1+m)%m;}

else {continue;}

}

p=g[father2g[fatherfind(i,j)]];

yes=1;

while (p!=NULL)

{

if (p->t==father2g[fatherfind(i1,j1)])

{

yes=0;

break;

}

p=p->next;

}

if (yes)

{

p=(struct link*)malloc(sizeof(struct
link));

p->next=g[father2g[fatherfind(i,j)]];

p->t=father2g[fatherfind(i1,j1)];

p->s=value[p->t]>=0?1:0;

g[father2g[fatherfind(i,j)]]=p;

}

}

}

}

}

GUI构架简介

出于平台兼容性考虑使用的是pythonQT的GUI形式,其中表格部分为输入部分,取一个最小的能包含所有输入部分的矩形作为输入成分,其中没有输入的部分认为输入的0,一共有两个Tab卡可以进行两个矩阵的输入操作。OK键表示根据右侧选项check后将其提交运算,标黄的为选择的部分。RESET会将所有数字清空。在一开始,我一不小心把UI文件中增加了计算成分,但在组员的提醒下,我分开了这两部分,把计算部分作为一个子类继承UI类,在其中重写一些按钮的方法,并加入计算成分。并且将调用算法的模式敲定为dll调用。

项目流程

首先通过C写算法部分的代码,在组员的提醒下,了解到啊并不需要在C的情况下写界面,由此换用更加高效的开发方式,介于MFC已经过时,我们没有采取这种VC6.0时代的组建方式。而对于C#构建的界面,虽然已然开发起来很方便,但仍然不具备跨平台的特点,于是我们组准备使用QT。为了体验一次跨语言编程架构的感觉,我们最终敲定使用PYQT。

而现在对.h文件有了更加深入的理解,即只声明而不划分内存,这与之前浅薄的了解不同,.h并不意味着是一个函数库,dll才是,.h只是起一个声明作用,其作用举一例说明便是把.h.dll都发送给二次编写者,以此保证其对自己的依赖性的同时不泄露代码,而GUI部分则无需要特别好的实现效率,于是便使用了PYQT的高开发效率的特性。并且学会了使用md语言。先使用ERIC4提供的QTdesigner绘制框架再通过ERIC4向python编译,再用自己写的窗口类继承setui后,完成GUI设计流程。

Personal Software Process Stages

时间百分比(%)

实际花费的时间 (分钟)

原来估计的时间 (分钟)

Planning

计划

10

·        
Estimate

·         估计这个任务需要多少时间,把工作细化并大致排序

10

Development

开发

80

·        
Analysis

·         需求分析 (包括学习新技术)

15

·        
Design Spec

·         生成设计文档

10

·        
Design Review

·         设计复审 (和同事审核设计文档)

5

·        
Coding Standard

·         代码规范 (制定合适的规范)

10

·        
Design

·         具体设计

5

·        
Coding

·         具体编码

15

·         Code
Review

·         代码复审

5

·         Test

·         测试(自我测试,修改代码,提交修改)

15

Reporting

总结报告

10

·         Test Report

·         测试报告

5

·         Size Measurement

·         计算工作量

3

·         Postmortem & Improvement Plan

·         事后总结, 并提出改进

2

Total

总计

100%

总用时

总估计的用时 系数为5小时,与计划差不多~

work3的更多相关文章

  1. python - work3

    # -*- coding:utf-8 -*- '''@project: jiaxy@author: Jimmy@file: work_20181107.py@ide: PyCharm Communit ...

  2. Node.js:进程、子进程与cluster多核处理模块

    1.process对象 process对象就是处理与进程相关信息的全局对象,不需要require引用,且是EventEmitter的实例. 获取进程信息 process对象提供了很多的API来获取当前 ...

  3. C#线程池使用

    bool stop; private void button3_Click(object sender, EventArgs e) { if(button3.Text=="线程池" ...

  4. 前端页面使用 Json对象与Json字符串之间的互相转换

    前言 在前端页面很多时候都会用到Json这种格式的数据,最近没有前端,后端的我也要什么都要搞,对于Json对象与Json字符串之间的转换终于摸清楚了几种方式,归纳如下! 一:Json对象转换为json ...

  5. C# 并行编程 之 轻量级手动重置事件的使用

    目录(?)[-] 简单介绍 使用超时和取消 跨进程或AppDomain的同步   简单介绍 如果预计操作的等待的时间非常短,可以考虑使用轻量级的手动重置事件,ManualResetEventSlim. ...

  6. 【JAVA】调用类中的属性

    class person { String name; int age; String like; void setName(String name) { this.name = name; } vo ...

  7. 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法

    BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...

  8. bzoj3283: 运算器

    #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...

  9. hdu 4897 Little Devil I

    传送阵:http://acm.hdu.edu.cn/showproblem.php?pid=4897 题目大意:一棵树,三个操作:1.将某条链取反,2.将与某条链相邻的边取反,3.查询某条链上为1的边 ...

随机推荐

  1. HDU 3757 Evacuation Plan DP

    跟 UVa 1474 - Evacuation Plan 一个题,但是在杭电上能交过,在UVa上交不过……不知道哪里有问题…… 将施工队位置和避难所位置排序. dp[i][j] 代表前 i 个避难所收 ...

  2. Asterisk服务安装配置和启动

    Asterisk服务安装配置和启动 2014年11月4日 11:36 注意: 更新源的重要性 源的地址: http://fffo.blog.163.com/blog/static/2119130682 ...

  3. IOSSelector的用法

    1.首先,@selector 里面的方法不能传参数..不要相信网上的..都是复制粘贴的.2.分三步走:1.设置tag.2.设置btn的调用方法.3.使用参数2.看示例代码把..   UIButton ...

  4. 如何过滤 adb logcat 输出

    对原作者表示感谢,转自博客:http://www.otechu.me/zh/2011/12/filtering-adb-logcat-output/ 本文介绍如何在 shell 命令行中过滤 adb ...

  5. 如何使用UIAutomation进行iOS 自动化测试(Part I)

    转自:http://www.cnblogs.com/vowei/archive/2012/08/10/2631949.html 写在前面 研究iOS的自动化测试也有些日子了,刚开始的时候,一直苦于找不 ...

  6. 为什么多数游戏服务端是用 C++ 来写

    早年开发游戏必须用C++,这没得说,2000-2004年,java还没有nio,其他动态语言不抗重负,只能C/C++能开发出完整可用的游戏服务端.直到2005年,韩国的游戏很多都还是纯C++写服务端, ...

  7. linux 服务自动调用

    php服务地址: http://192.168.2.117/web/index.php/buy/auctionselect 编写脚本service.sh,内容: #! /bin/sh crul htt ...

  8. FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法。。

    [原创] RFC3984是H.264的baseline码流在RTP方式下传输的规范,这里只讨论FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法. 1.单个NAL包单元 12字节 ...

  9. DrawDibDraw函数的使用方法

    使用windows的的自带的函数来显示图像可能始终还是绕不开两个概念, 视口和窗口. 视口--- 屏幕上的一个显示用的矩形框. 窗口--- 完整图像上的一个用于取数的矩形框. 屏幕的宽度.高度和视口参 ...

  10. DirectX截图黑屏的解决办法

    好久没有更新博客了,今天开始继续耕耘. 生活要继续 工作要继续 梦想也一定要继续! 之前写过一篇关于DirectX截屏的文章,其中有网友留言提到了截图黑屏的问题,于是这些日子研究了一下,与大家一同分享 ...