work3
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 |
||
· |
· 估计这个任务需要多少时间,把工作细化并大致排序 |
10 |
||
Development |
开发 |
80 |
||
· |
· 需求分析 (包括学习新技术) |
15 |
||
· |
· 生成设计文档 |
10 |
||
· |
· 设计复审 (和同事审核设计文档) |
5 |
||
· |
· 代码规范 (制定合适的规范) |
10 |
||
· |
· 具体设计 |
5 |
||
· |
· 具体编码 |
15 |
||
· Code |
· 代码复审 |
5 |
||
· Test |
· 测试(自我测试,修改代码,提交修改) |
15 |
||
Reporting |
总结报告 |
10 |
||
· Test Report |
· 测试报告 |
5 |
||
· Size Measurement |
· 计算工作量 |
3 |
||
· Postmortem & Improvement Plan |
· 事后总结, 并提出改进 |
2 |
||
Total |
总计 |
100% |
总用时 |
总估计的用时 系数为5小时,与计划差不多~ |
work3的更多相关文章
- python - work3
# -*- coding:utf-8 -*- '''@project: jiaxy@author: Jimmy@file: work_20181107.py@ide: PyCharm Communit ...
- Node.js:进程、子进程与cluster多核处理模块
1.process对象 process对象就是处理与进程相关信息的全局对象,不需要require引用,且是EventEmitter的实例. 获取进程信息 process对象提供了很多的API来获取当前 ...
- C#线程池使用
bool stop; private void button3_Click(object sender, EventArgs e) { if(button3.Text=="线程池" ...
- 前端页面使用 Json对象与Json字符串之间的互相转换
前言 在前端页面很多时候都会用到Json这种格式的数据,最近没有前端,后端的我也要什么都要搞,对于Json对象与Json字符串之间的转换终于摸清楚了几种方式,归纳如下! 一:Json对象转换为json ...
- C# 并行编程 之 轻量级手动重置事件的使用
目录(?)[-] 简单介绍 使用超时和取消 跨进程或AppDomain的同步 简单介绍 如果预计操作的等待的时间非常短,可以考虑使用轻量级的手动重置事件,ManualResetEventSlim. ...
- 【JAVA】调用类中的属性
class person { String name; int age; String like; void setName(String name) { this.name = name; } vo ...
- 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法
BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...
- bzoj3283: 运算器
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...
- hdu 4897 Little Devil I
传送阵:http://acm.hdu.edu.cn/showproblem.php?pid=4897 题目大意:一棵树,三个操作:1.将某条链取反,2.将与某条链相邻的边取反,3.查询某条链上为1的边 ...
随机推荐
- HDU 3757 Evacuation Plan DP
跟 UVa 1474 - Evacuation Plan 一个题,但是在杭电上能交过,在UVa上交不过……不知道哪里有问题…… 将施工队位置和避难所位置排序. dp[i][j] 代表前 i 个避难所收 ...
- Asterisk服务安装配置和启动
Asterisk服务安装配置和启动 2014年11月4日 11:36 注意: 更新源的重要性 源的地址: http://fffo.blog.163.com/blog/static/2119130682 ...
- IOSSelector的用法
1.首先,@selector 里面的方法不能传参数..不要相信网上的..都是复制粘贴的.2.分三步走:1.设置tag.2.设置btn的调用方法.3.使用参数2.看示例代码把.. UIButton ...
- 如何过滤 adb logcat 输出
对原作者表示感谢,转自博客:http://www.otechu.me/zh/2011/12/filtering-adb-logcat-output/ 本文介绍如何在 shell 命令行中过滤 adb ...
- 如何使用UIAutomation进行iOS 自动化测试(Part I)
转自:http://www.cnblogs.com/vowei/archive/2012/08/10/2631949.html 写在前面 研究iOS的自动化测试也有些日子了,刚开始的时候,一直苦于找不 ...
- 为什么多数游戏服务端是用 C++ 来写
早年开发游戏必须用C++,这没得说,2000-2004年,java还没有nio,其他动态语言不抗重负,只能C/C++能开发出完整可用的游戏服务端.直到2005年,韩国的游戏很多都还是纯C++写服务端, ...
- linux 服务自动调用
php服务地址: http://192.168.2.117/web/index.php/buy/auctionselect 编写脚本service.sh,内容: #! /bin/sh crul htt ...
- FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法。。
[原创] RFC3984是H.264的baseline码流在RTP方式下传输的规范,这里只讨论FU-A分包方式,以及从RTP包里面得到H.264数据和AAC数据的方法. 1.单个NAL包单元 12字节 ...
- DrawDibDraw函数的使用方法
使用windows的的自带的函数来显示图像可能始终还是绕不开两个概念, 视口和窗口. 视口--- 屏幕上的一个显示用的矩形框. 窗口--- 完整图像上的一个用于取数的矩形框. 屏幕的宽度.高度和视口参 ...
- DirectX截图黑屏的解决办法
好久没有更新博客了,今天开始继续耕耘. 生活要继续 工作要继续 梦想也一定要继续! 之前写过一篇关于DirectX截屏的文章,其中有网友留言提到了截图黑屏的问题,于是这些日子研究了一下,与大家一同分享 ...