wzy2001wzy

导航

BUAA面向对象2022第三单元总结

BUAA面向对象2022第三单元总结

总览

作业内容

本单元的主要作业内容为读JML并实现一个Network,实际上就是对图的一些操作。共有3次作业,为迭代开发。

第一次作业需要实现加人,加关系,求关系图可达性,求关系图连通块个数以及一些异常情况的处理。

第二次作业增加了发消息,求群成员各种属性,以及求关系图最小生成树和消息相关的异常。

第三次作业加入多种不同类型的消息的处理,以及一个间接消息发送(求最短路)。

完成情况

这单元没啥思维含量,直接写就行,但是细节比较多。

第一次作业没有错误。

第二次作业没有看到群内最多1111人,互测被干了。

第三次作业给群发红包后发送者的钱算错了,互测被干了 (这强测没错我不能理解)

互测情况:三次作业 发起/受到hack 分别为 0/0 , 4/6 , 0/1 。

hack了两个qgvs写的太丑tle的。

实现过程

总体思路

其实大部分按照JML写就行。然后就是怎么方便怎么来,JML规格里的数组可以用HashMap来实现,这样就可以快速通过id找到对应的人/组了。

难点

有几个方法可能不能完全按照JML的规格来写,需要一些简化。

isCircle:判断关系图中两人是否可达,用并查集即可,顺便可以把queryBlockSum也维护了。

queryLeastConnection:最小生成树,直接跑一遍prim就行。

queryGroupValueSum:这个不能用两层循环,否则会TLE,应该遍历边。

sendIndirectMessage:需要求一个最短路,跑一边dij就行。

总体来说就是保证每次复杂度都在O(N)这个级别就行,qlc和sim因为次数有限制,可以多带个log。

毕竟不是算法课,就懒得去优化复杂度了。

扩展内容

新建Product类,有id,name,price等属性。

新建Advertiser,Producer,Customer类分别继承Person类。

新建Advertisement类, 有id,productId ,producer等属性。

NetWork中增加products,advertisements数组。

下面是三个关键方法(produce:生产物品,advertise:发送广告,buyProduct:购买物品)的JML。

为了简便,忽略了id不存在,id不对应,id重复等异常。

 /*@ public normal_behavior
  @ assignable products;
  @ ensures products.length == \old(products.length) + 1;
  @ ensures (\forall int i; 0 <= i && i < \old(products.length);
  @         (\exists int j; 0 <= j && j < products.length; products[j] == (\old(products[i]))));
  @ ensures (\exists int i; 0 <= i && i < products.length; products[i] == product);
*/
public void produce(/* non_null */ Product product);
 /*@ public normal_behavior
  @ assignable advertisenments;
  @ ensures advertisenments.length == \old(advertisenments.length) + 1;
  @ ensures (\forall int i; 0 <= i && i < \old(advertisenments.length);
  @         (\exists int j; 0 <= j && j < advertisenments.length; advertisenments[j] == (\old(advertisenments[i]))));
  @ ensures (\exists int i; 0 <= i && i < advertisenments.length; advertisenments[i] == advertisenment);
*/
public void advertise(/* non_null */ Advertisement advertisement);
 /*@ public normal_behavior
  @ assignable getPerson(custId).money,getPerson(getAdv(advId).getProducer()).money;
  @ assignable products;
  @ ensures !containsProduct(getAdv(advId).getProductId()) && products.length == \old(products.length) - 1 &&
     @         (\forall int i; 0 <= i && i < \old(products.length) && \old(products[i].getId()) != getAdv(advId).getProductId();
     @         (\exists int j; 0 <= j && j < products.length; products[j].equals(\old(products[i]))));
  @ ensures getPerson(custId).money = \old(getPerson(custId).money) - getProduct(getAdv(advId).getProductId()).getPrice();
  @ ensures getPerson(getAdv(advId).getProducer()).money = \old(getPerson(getAdv(advId).getProducer()).money) + getProduct(getAdv(advId).getProductId).getPrice();
*/
public void buy(int custId, int advId)

 

总结与反思

List有个removeIf方法挺好用的,避免了边遍历边删除的尴尬处境,也不用写很多行代码。

Java的HashMap很高级,Hash冲突多了会用平衡树存同一个hash值的玩意,不能卡成线性。

还是要认真读题。

 

posted on 2022-06-03 16:08  我没有名称  阅读(13)  评论(0编辑  收藏  举报