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. php库Faker

    Faker License : MIT Source Code Allo点评:Faker是一个很神奇的项目,会自动生成拟真的数据,包括用户资料.长文本.IP.日期等等,在网站上线前测试时非常好用. g ...

  2. BZOJ 2299 向量

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2299 题意:给出一对数a,b,任意使用(a,b), (a,-b), (-a,b), (- ...

  3. C++ 中字符串标准输入的学习及实验

    声明:下面实验中[]里面表示要输入里面的符号,[]符号本身并未输入 1.cin>> cin使用空白(空格.制表符.回车)来确定字符串的结束位置. cin会将换行符留在输入输出队列中. #i ...

  4. Jquery实现让滚动条始终保持在最下方

    $(document).ready(function(){ $("#submit").click(function(){ $("#info").append(& ...

  5. HDU 1280 前m大的数【哈希入门】

    题意:中文的题目= =将各种组合可能得到的和作为下标,然后因为不同组合得到的和可能是一样的, 所以再用一个数组num[]数组,就可以将相同的和都记录下来 #include<iostream> ...

  6. fancybox 点击 js脚本判断验证,fancybox的宽度高度设置

    当我们在使用fancybox做弹出窗口的时候,可能在弹窗之前就需要判断一些验证条件,例如我这里有个案例,用户必须先得勾选一个 那么怎么做呢?我们用到fancybox的一个onStart方法就可以了 $ ...

  7. Java [Leetcode 204]Count Primes

    题目描述: Description: Count the number of prime numbers less than a non-negative number, n. 解题思路: Let's ...

  8. [Everyday Mathematics]20150129

    计算下列积分 $$\bex \int_a^b (x-a)^2(b-x)^3\rd x. \eex$$

  9. 【Android】以BaseAdapter做适配器的ListView及其性能优化

    适配器的Java类 package com.app.adapter; import org.json.JSONArray; import org.json.JSONObject; import and ...

  10. IOS 第三方开源库记录

    网易客户端使用 1.ZipArchive 2.wax 3.TTTAttributedLabel 4.SSKeychain 5.SDWebImage 6.RegexKitLite 7.pop 8.NJK ...