mobile.365-838.comSwift 中枚举高级用法及执行

By admin in mobile.365-838.com on 2019年3月5日

title: “Swift 中枚举高级用法及执行”
date: 2015-11-20
tags: [APPVENTURE]
categories: [Swift 进阶]
permalink: advanced-practical-enum-examples

1.


[HNOI2001]
产品加工

原来的书文链接=http://appventure.me/2015/10/17/advanced-practical-enum-examples/
作者=Benedikt Terhechte
初稿日期=二零一四-10-17
译者=pmst+小锅
校对=shanks
定稿=shanks

一道不难的背包,可是笔者或然写了很久QAQ
 

翻译注:作为贰个走心且有逼格的翻译组,大家对本篇小说中的代码都开始展览了注解,并且写了将代码分为前后两篇做成了
playground,代码中有详尽的诠释。能够到本条github地址上拓展下载,那几个代码由翻译组的另壹人小伙子伴
ppt
提供。

时刻限定是都低于5
分明考虑一维背包,dp[i]表示近年来A消耗了i的蝇头B消耗

本文是一篇详细且全部实战意义的课程,涵盖差不多拥有枚举(Enum)知识点,为您解答Swift中枚举的选拔地方以及选择格局。

注意

switch语句类似,Swift中的枚举乍看之下更像是C语言中枚举的进阶版本,即允许你定义一体系型,用于表示经常工作中某种用例。然而深切挖潜之后,凭借Swift背后尤其的筹划意见,相相比C语言枚举来说其在实际情形中的应用尤其常见。尤其是用作强大的工具,Swift中的枚举能够清楚表明代码的意图。

 if(b[i])
dp[j]=dp[j]+b[i];
 else dp[j]=1e9+7;

正文中,我们将首先精通基础语法和运用枚举的恐怕性,接着通超过实际战教您怎么以及何时使用枚举。最终大家还会大体明白下Swift专业库中枚举是哪些被运用的。

能够用B则向来转移,不然要把上3次的这一个状态设为正无穷,只能用后八个转移。

正式启幕攻读在此以前,先给出枚举的定义。之后我们将回过头再来钻探它。

 

枚举表明的门类是回顾大概景况的有限集,且能够具有附加值。通过内嵌(nesting),方法(method),关联值(associated
values
)和方式匹配(pattern
matching
),枚举能够分层次地定义任何有集体的数额。

mobile.365-838.com 1mobile.365-838.com 2

深远掌握(Diving In)

简短概述怎么样定义和利用枚举。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=6000+299;
const int N=5*6000+9;
int n,a[maxn],b[maxn],c[maxn],dp[N],lz[N],ans=1e9+7; 
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]);
    memset(dp,127,sizeof(dp));
    dp[0]=0;
    for(int i=1;i<=n;i++)
        for(int j=i*5;j>=0;j--){
            if(b[i]) dp[j]=dp[j]+b[i];
            else dp[j]=1e9+7;//!!!!!!!!!!!!!!!!!!!!
            if(a[i]&&j>=a[i]&&dp[j]>dp[j-a[i]]) dp[j]=dp[j-a[i]];
            if(c[i]&&j>=c[i]&&dp[j]>dp[j-c[i]]+c[i]) dp[j]=dp[j-c[i]]+c[i];
            if(i==n) ans=min(max(dp[j],j),ans);
        }
    cout<<ans;
    return 0;
}

概念基本的枚举类型(Defining Basic Enums)

试想我们正在开发一款游戏,玩家能够朝多个趋势移动。所以喽,玩家的活动轨迹受到了限定。明显,大家能够利用枚举来表述这一动静:

enum Movement{
    case Left
    case Right
    case Top
    case Bottom
}

进而,你能够应用各种方式匹配结构获取到Movement的枚举值,或许依照一定情景实行操作:

let aMovement = Movement.Left

// switch 分情况处理
switch aMovement{
case .Left: print("left")
default:()
}

// 明确的case情况
if case .Left = aMovement{
    print("left")
}

if aMovement == .Left { print("left") }

案例中,我们不用鲜明提出enum的其实名称(即case Move.Left:print("Left"))。因为品种检查器能够自动为此开始展览项目推算。那对于那多少个UIKit以及AppKit中错综复杂的枚举是灰常有用的。

View
Code

枚举值(Enum Values)

理所当然,你恐怕想要为enum中每个case分配3个值。这一定有用,比如枚举本人实际与某事或某物挂钩时,往往那些东西又需求运用不相同连串来宣布。在C言语中,你不得不为枚举case分配整型值,而Swift则提供了越多的灵活性。

// 映射到整型
enum Movement: Int {
    case Left = 0
    case Right = 1
    case Top = 2
    case Bottom = 3
}

// 同样你可以与字符串一一对应
enum House: String {
    case Baratheon = "Ours is the Fury"
    case Greyjoy = "We Do Not Sow"
    case Martell = "Unbowed, Unbent, Unbroken"
    case Stark = "Winter is Coming"
    case Tully = "Family, Duty, Honor"
    case Tyrell = "Growing Strong"
}

// 或者float double都可以(同时注意枚举中的花式unicode)
enum Constants: Double {
    case π = 3.14159
    case e = 2.71828
    case φ = 1.61803398874
    case λ = 1.30357
}

对于StringInt类型来说,你还可以够忽略为枚举中的case赋值,Swift编写翻译器也能健康干活。

// Mercury = 1, Venus = 2, ... Neptune = 8
enum Planet: Int {
    case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

// North = "North", ... West = "West"
// 译者注: 这个是swift2.0新增语法
enum CompassPoint: String {
    case North, South, East, West
}

Swift枚举中帮助以下五种关联值类型:

  • 整型(Integer)
  • 浮点数(Float Point)
  • 字符串(String)
  • 布尔类型(Boolean)

故此你不能1为枚举分配诸如CGPoint花色的值。

只要你想要读取枚举的值,能够透过rawValue个性来贯彻:

let bestHouse = House.Stark
print(bestHouse.rawValue)
// prints "Winter is coming"

唯独某种景况下,你恐怕想要通过二个已有个别raw value来创建多少个enum case。那种景观下,枚举提供了三个钦点构造方法:

enum Movement: Int {
    case Left = 0
    case Right = 1
    case Top = 2
    case Bottom = 3
}
// 创建一个movement.Right 用例,其raw value值为1
let rightMovement = Movement(rawValue: 1)

比方使用rawValue构造器,切记它是三个可难倒构造器(failable
initializer
)。换言之,构造方法再次来到值为可选类型值,因为偶然传入的值恐怕与自由3个case都不般配。比如Movement(rawValue:42)

如果你想要以底层 C
二进制编码格局突显某物或某事,使得更具可读性,那是一个相当实惠的功力。例如,能够看一下BSD
kqeue
library
中的VNode
Flags
标明位的编码方式:

enum VNodeFlags : UInt32 {
    case Delete = 0x00000001
    case Write = 0x00000002
    case Extended = 0x00000004
    case Attrib = 0x00000008
    case Link = 0x00000010
    case Rename = 0x00000020
    case Revoke = 0x00000040
    case None = 0x00000080
}

那样便能够使你的DeleteWrite用例声澳优目精晓,稍后一旦需求,只需将raw
value
流传 C 函数中即可。

 

嵌套枚举(Nesting Enums)

若是您有特定子类型的须要,能够对enum进行嵌套。那样就允许你为实际的enum中隐含其余显著音信的enum。以RPG玩耍中的每一个角色为例,每种剧中人物能够拥有武器,由此有着剧中人物都足以赢得同贰个军火集合。而娱乐中的其余实例则无从得到那一个武器(比如食人魔,它们仅使用棍棒)。

enum Character {
  enum Weapon {
    case Bow
    case Sword
    case Lance
    case Dagger
  }
  enum Helmet {
    case Wooden
    case Iron
    case Diamond
  }
  case Thief
  case Warrior
  case Knight
}

未来,你可以透过层级结构来讲述角色允许访问的项目条。

let character = Character.Thief
let weapon = Character.Weapon.Bow
let helmet = Character.Helmet.Iron

2.

富含枚举(Containing Enums)

平等地,你也可以在structsclasses中内嵌枚举。接着上边的例证:

struct Character {
   enum CharacterType {
    case Thief
    case Warrior
    case Knight
  }
  enum Weapon {
    case Bow
    case Sword
    case Lance
    case Dagger
  }
  let type: CharacterType
  let weapon: Weapon
}

let warrior = Character(type: .Warrior, weapon: .Sword)

一样地,那也将助长大家将相关的消息汇总在两个地点。

[HAOI2007]上涨体系

关联值(Associated Value)

关联值是将额外音讯附加到enum case中的一种极好的措施。打个比方,你正在开发一款交易引擎,只怕存在三种不相同的交易类型。除此之外每手交易还要制定明显的股票名称和交易数据:

看数量范围就好像是n^2能够过的,可是自身在此以前并不会写nlongn求最长上升子种类的算法就融洽YY了弹指间,写得极难看,单调栈里从短到长从大到小,用了七个二分,二回找找最长的比它小的,1遍找长度为它的地方是还是不是足以立异。

简短例程(Simple Example)

enum Trade {
    case Buy
    case Sell
}
func trade(tradeType: Trade, stock: String, amount: Int) {}

然而股票的股票总值和数量明显从属于交易,让她们当作独立的参数显得首鼠两端。你可能早就想到要往struct中内嵌贰个枚举了,不过关联值提供了一种更舒服的消除方案:

enum Trade {
    case Buy(stock: String, amount: Int)
    case Sell(stock: String, amount: Int)
}
func trade(type: Trade) {}

如此找到以每一种成分打头的最长上涨连串,询问就从1到n跑二次问它能还是无法到那么长,就确定保证了字典序最小。

形式匹配(Pattern Mathching)

假使您想要访问那个值,情势匹配双重救场:

let trade = Trade.Buy(stock: "APPL", amount: 500)
if case let Trade.Buy(stock, amount) = trade {
    print("buy \(amount) of \(stock)")
}

mobile.365-838.com 3mobile.365-838.com 4

标签(Labels)

提到值不要求增大标价签的宣示:

enum Trade {
   case Buy(String, Int)
   case Sell(String, Int)
}

设若你添加了,那么,每当创建枚举用例时,你都亟需将那个标签标示出来。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<vector>
using namespace std;
const int maxn=10000+299;
int now,n,m,x,maxx,a[maxn],pre[maxn],dp[maxn],sta[maxn],sl=1,sr;
int ef(int l,int r,int x){
    int res=-1;
    while(l<=r){
        int mid=(l+r)>>1;
        if(a[sta[mid]]>x) res=mid,l=mid+1;
        else r=mid-1;
    }
    return res;
}
void ef2(int l,int r,int len,int x){
    while(l<=r){
        int mid=(l+r)>>1;
        if(dp[sta[mid]]==len) { if(a[sta[mid]]<=a[x]) sta[mid]=x; break;}
        if(dp[sta[mid]]<len) l=mid+1;
        else if(dp[sta[mid]]>len) r=mid-1;  
    }
}
void work() { 
    for(int i=n;i>=1;i--) {
        dp[i]=1;
        if(sl<=sr) {
        now=ef(sl,sr,a[i]);
        if(now!=-1)
            dp[i]=dp[sta[now]]+1;
        }
        maxx=max(maxx,dp[i]);
        while(sr>=sl&&dp[sta[sr]]<=dp[i]&&a[sta[sr]]<=a[i]) {
            sr--;
        }
        if(sr<sl||dp[sta[sr]]<dp[i]) sta[++sr]=i;
        else ef2(sl,sr,dp[i],i);
    }
}
void query(int x){
    if(x>maxx) puts("Impossible");
    else {
        int pre=0;
        for(int i=1;i<=n;i++) {
            if(dp[i]>=x&&a[i]>pre) {
                pre=a[i];
                if(x==1)
                printf("%d",a[i]);
                else printf("%d ",a[i]);
                x--;
                if(!x) break;
            }
        }
        printf("\n");
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    work();
    scanf("%d",&m);
    for(int i=1;i<=m;i++) {
        scanf("%d",&x);
        query(x); 
    }
    return 0;
}

(元组参数)Tuple as Arguments

更注重的是,Swift其间有关音讯实际是三个元组,所以你能够像上边那样做:

let tp = (stock: "TSLA", amount: 100)
let trade = Trade.Sell(tp)

if case let Trade.Sell(stock, amount) = trade {
    print("buy \(amount) of \(stock)")
}
// Prints: "buy 100 of TSLA"

语法允许你将元组当作3个不难的数据结构,稍后元组将电动转换成高级项目,就比如enum case。想象一个应用程序能够让用户来安排电脑:

typealias Config = (RAM: Int, CPU: String, GPU: String)

// Each of these takes a config and returns an updated config
func selectRAM(_ config: Config) -> Config {return (RAM: 32, CPU: config.CPU, GPU: config.GPU)}
func selectCPU(_ config: Config) -> Config {return (RAM: config.RAM, CPU: "3.2GHZ", GPU: config.GPU)}
func selectGPU(_ config: Config) -> Config {return (RAM: config.RAM, CPU: "3.2GHZ", GPU: "NVidia")}

enum Desktop {
   case Cube(Config)
   case Tower(Config)
   case Rack(Config)
}

let aTower = Desktop.Tower(selectGPU(selectCPU(selectRAM((0, "", "") as Config))))

配备的各类步骤均经过递交元组到enum中展开内容更新。要是我们从函数式编制程序2中收获启发,那将变得更好。

infix operator <^> { associativity left }

func <^>(a: Config, f: (Config) -> Config) -> Config { 
    return f(a)
}

最后,大家得以将区别布置步骤串联起来。那在安插步骤繁多的动静下一定实惠。

let config = (0, "", "") <^> selectRAM  <^> selectCPU <^> selectGPU
let aCube = Desktop.Cube(config)

View
Code

应用案例(Use Case Example)

关联值能够以多种办法利用。常言道:一码胜千言,
上面就上几段不难的言传身教代码,这几段代码没有一定的逐条。

// 拥有不同值的用例
enum UserAction {
  case OpenURL(url: NSURL)
  case SwitchProcess(processId: UInt32)
  case Restart(time: NSDate?, intoCommandLine: Bool)
}

// 假设你在实现一个功能强大的编辑器,这个编辑器允许多重选择,
// 正如 Sublime Text : https://www.youtube.com/watch?v=i2SVJa2EGIw
enum Selection {
  case None
  case Single(Range<Int>)
  case Multiple([Range<Int>])
}

// 或者映射不同的标识码
enum Barcode {
    case UPCA(numberSystem: Int, manufacturer: Int, product: Int, check: Int)
    case QRCode(productCode: String)
}

// 又或者假设你在封装一个 C 语言库,正如 Kqeue BSD/Darwin 通知系统:
// https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
enum KqueueEvent {
    case UserEvent(identifier: UInt, fflags: [UInt32], data: Int)
    case ReadFD(fd: UInt, data: Int)
    case WriteFD(fd: UInt, data: Int)
    case VnodeFD(fd: UInt, fflags: [UInt32], data: Int)
    case ErrorEvent(code: UInt, message: String)
}

// 最后, 一个 RPG 游戏中的所有可穿戴装备可以使用一个枚举来进行映射,
// 可以为一个装备增加重量和持久两个属性
// 现在可以仅用一行代码来增加一个"钻石"属性,如此一来我们便可以增加几件新的镶嵌钻石的可穿戴装备
enum Wearable {
    enum Weight: Int {
    case Light = 1
    case Mid = 4
    case Heavy = 10
    }
    enum Armor: Int {
    case Light = 2
    case Strong = 8
    case Heavy = 20
    }
    case Helmet(weight: Weight, armor: Armor)
    case Breastplate(weight: Weight, armor: Armor)
    case Shield(weight: Weight, armor: Armor)
}
let woodenHelmet = Wearable.Helmet(weight: .Light, armor: .Light)

 

方法和性格(Methods and properties)

你也足以在enum中像那样定义方法:

enum Wearable {
    enum Weight: Int {
        case Light = 1
    }
    enum Armor: Int {
        case Light = 2
    }
    case Helmet(weight: Weight, armor: Armor)
        func attributes() -> (weight: Int, armor: Int) {
       switch self {
             case .Helmet(let w, let a): return (weight: w.rawValue * 2, armor: w.rawValue * 4)
       }
    }
}
let woodenHelmetProps = Wearable.Helmet(weight: .Light, armor: .Light).attributes()
print (woodenHelmetProps)
// prints "(2, 4)"

枚举中的方法为每贰个enum case而“生”。所以假使想要在特定情景实施一定代码的话,你必要分支处理或使用switch语句来显然无误的代码路径。

enum Device { 
    case iPad, iPhone, AppleTV, AppleWatch 
    func introduced() -> String {
       switch self {
         case AppleTV: return "\(self) was introduced 2006"
         case iPhone: return "\(self) was introduced 2007"
         case iPad: return "\(self) was introduced 2010"
         case AppleWatch: return "\(self) was introduced 2014"
       }
    }
}
print (Device.iPhone.introduced())
// prints: "iPhone was introduced 2007"

 

属性(Properties)

即使扩张一个囤积属性到枚举中不被允许,但你仍旧能够创建计算属性。当然,总计属性的内容都是起家在枚举值下恐怕枚举关联值获得的。

enum Device {
  case iPad, iPhone
  var year: Int {
    switch self {
        case iPhone: return 2007
        case iPad: return 2010
     }
  }
}

而是正确的nlogn求最长上升系列并不是如此写的,只用二个二分,可是在下并不是很明亮,懒得学未来再说吧。

静态方法(Static Methods)

您也能够为枚举创制一些静态方法(static methods)。换言之通过八个非枚举类型来创制八个枚举。在这些示例中,大家须求考虑用户有时将苹果设备叫错的状态(比如Apple沃特ch叫成i沃特ch),需求回到3个恰如其分的称谓。

enum Device { 
    case AppleWatch 
    static func fromSlang(term: String) -> Device? {
      if term == "iWatch" {
      return .AppleWatch
      }
      return nil
    }
}
print (Device.fromSlang("iWatch"))

从LLJ大佬那里学到了用线段树的做法,开一颗权值线段树,从后往前把Dp值存进去,每一种点找它背后的最大Dp值来更新,感觉和健康的nlogn的笔触大概大多。

可变方法(Mutating Methods)

办法能够表明为mutating。那样就同意改变隐藏参数selfcase值了3

enum TriStateSwitch {
    case Off, Low, High
    mutating func next() {
    switch self {
    case Off:
        self = Low
    case Low:
        self = High
    case High:
        self = Off
    }
    }
}
var ovenLight = TriStateSwitch.Low
ovenLight.next()
// ovenLight 现在等于.On
ovenLight.next()
// ovenLight 现在等于.Off

 

小结(To Recap)

从那之后,大家已经大致精晓了Swift中枚举语法的大旨用例。在伊始迈向进阶之路之前,让大家再度审视小说开篇给出的概念,看看未来是或不是变得更清晰了。

枚举阐明的种类是回顾大概情状的有限集,且能够具有附加值。通过内嵌(nesting),方法(method),关联值(associated
values
)和形式匹配(pattern
matching
),枚举能够分层次地定义任何有团体的数量。

现在大家曾经对那个概念尤其清楚了。确实,若是大家添加关联值和嵌套,enum就看起来就像一个封闭的、简化的struct。相比较struct,前者优势映今后能够为分类与层次结构编码。

// Struct Example
struct Point { let x: Int, let y: Int }
struct Rect { let x: Int, let y: Int, let width: Int, let height: Int }

// Enum Example
enum GeometricEntity {
   case Point(x: Int, y: Int)
   case Rect(x: Int, y: Int, width: Int, height: Int)
}

艺术和静态方法的增加同意大家为enum外加成效,那意味着无须依靠额外函数就能完成4

// C-Like example
enum Trade {
   case Buy
   case Sell
}
func order(trade: Trade)

// Swift Enum example
enum Trade {
   case Buy
   case Sell
   func order()
}

3.

枚举进阶(Advanced Enum Usage)

UVA – 12063 Zeros and
Ones

协议(Protocols)

小编一度提及了structsenums中间的相似性。除了附加措施的能力之外,Swift也允许你在枚举中选拔协议(Protocols)合计扩充(Protocol
Extension)

Swift商业事务定义3个接口或项目以供别的数据结构来遵守。enum本来也不例外。大家先从Swift标准库中的一个例证起始.

CustomStringConvertible是四个以打字与印刷为指标的自定义格式化输出的档次。

protocol CustomStringConvertible {
  var description: String { get }
}

该协议只有一个渴求,即一个只读(getter)类型的字符串(String项目)。大家得以很不难为enum贯彻这几个体协会议。

enum Trade: CustomStringConvertible {
   case Buy, Sell
   var description: String {
       switch self {
       case Buy: return "We're buying something"
       case Sell: return "We're selling something"
       }
   }
}

let action = Trade.Buy
print("this action is \(action)")
// prints: this action is We're buying something

有的说道的兑现或许必要依照当中景观来对号入座处理需求。例如定义一个管制银行账号的协议。

protocol AccountCompatible {
  var remainingFunds: Int { get }
  mutating func addFunds(amount: Int) throws
  mutating func removeFunds(amount: Int) throws
}

您或然会简单地拿struct落实那些体协会议,不过考虑选择的上下文,enum是多个更精明的拍卖方法。不过你无法添加叁个囤积属性到enum中,就像var remainingFuns:Int。那么你会什么协会呢?答案灰常简单,你能够利用关联值完美化解:

enum Account {
  case Empty
  case Funds(remaining: Int)

  enum Error: ErrorType {
    case Overdraft(amount: Int)
  }

  var remainingFunds: Int {
    switch self {
    case Empty: return 0
    case Funds(let remaining): return remaining
    }
  }
}

为了维持代码清爽,我们能够在enum的商议扩张(protocl extension)中定义必须的合计函数:

extension Account: AccountCompatible {

  mutating func addFunds(amount: Int) throws {
    var newAmount = amount
    if case let .Funds(remaining) = self {
      newAmount += remaining
    }
    if newAmount < 0 {
      throw Error.Overdraft(amount: -newAmount)
    } else if newAmount == 0 {
      self = .Empty
    } else {
      self = .Funds(remaining: newAmount)
    }
  }

  mutating func removeFunds(amount: Int) throws {
    try self.addFunds(amount * -1)
  }

}
var account = Account.Funds(remaining: 20)
print("add: ", try? account.addFunds(10))
print ("remove 1: ", try? account.removeFunds(15))
print ("remove 2: ", try? account.removeFunds(55))
// prints:
// : add:  Optional(())
// : remove 1:  Optional(())
// : remove 2:  nil

正如您所看见的,大家透过将值存款和储蓄到enum cases中贯彻了协和式飞机抱有要求项。如此做法还有2个有趣的地点:今后全方位代码基础上你只须要一个形式匹配就能测试空账号输入的场馆。你不供给关爱剩余资金是或不是等于零。

而且,大家也在账号(Accout)中内嵌了一个依据ErrorType共谋的枚举,这样我们就足以行使Swift2.0语法来进展错误处理了。这里给出更详尽的利用案例教程。

 

style=”font-family: "Microsoft YaHei"; font-size: 15px”>二进制数和它们的位情势对于电脑程序员来说总是充裕有意思的。
在这几个
style=”font-family: "Microsoft YaHei"; font-size: 15px”>您必要计算有所以下属性的正数二进制数的题材:
style=”font-family: "Microsoft YaHei"; font-size: 15px”>•数字正好是N位宽,它们没有前导零。
style=”font-family: "Microsoft YaHei"; font-size: 15px”>•一和零的频率极度。
style=”font-family: "Microsoft YaHei"; font-size: 15px”>•数字是K的倍数。
style=”font-family: "Microsoft YaHei"; font-size: 15px”>输入
style=”font-family: "Microsoft YaHei"; font-size: 15px”>输入文件包蕴多少个测试用例。
输入的首先作为您提供了测试用例数,
style=”font-family: "Microsoft YaHei"; font-size: 15px”>T(1≤T≤100)。
那么T测试用例会跟随,每一行都在一行。 各样测试用例的输入包涵
style=”font-family: "Microsoft YaHei"; font-size: 15px”>的八个整数,N(1≤N≤64)和K(0≤K≤100)。
style=”font-family: "Microsoft YaHei"; font-size: 15px”>产量
style=”font-family: "Microsoft YaHei"; font-size: 15px”>对于每组输入,首先打字与印刷测试用例编号。
然后打字与印刷二进制数的数字 style=”font-family: "Microsoft YaHei"”>

 

扩展(Extensions)

正如刚刚所见,枚举也得以展开扩展。最显然的用例就是将枚举的casemethod分离,这样阅读你的代码能够不难快捷地消化掉enum情节,紧接着转移到艺术定义:

enum Entities {
    case Soldier(x: Int, y: Int)
    case Tank(x: Int, y: Int)
    case Player(x: Int, y: Int)
}

现在,我们为enum增添方法:

extension Entities {
   mutating func move(dist: CGVector) {}
   mutating func attack() {}
}

你同一可以由此写一个恢宏来遵从三个特定的合计:

extension Entities: CustomStringConvertible {
  var description: String {
    switch self {
       case let .Soldier(x, y): return "\(x), \(y)"
       case let .Tank(x, y): return "\(x), \(y)"
       case let .Player(x, y): return "\(x), \(y)"
    }
  }
}

 

枚举泛型(Generic Enums)

枚举也支撑泛型参数定义。你能够利用它们以适应枚举中的关联值。就拿直接源于Swift标准库中的简单例子来说,即Optional类别。你根本大概因此以下二种办法利用它:可选链(optional chaining(?))、if-let可选绑定、guard let、或switch,不过从语法角度来说你也可以那样使用Optional:

let aValue = Optional<Int>.Some(5)
let noValue = Optional<Int>.None
if noValue == Optional.None { print("No value") }

这是Optional最直接的用例,并未使用其余语法糖,然则不可不可以认Swift中语法糖的加盟使得你的做事更简约。假若你观望位置的实例代码,你或然早已猜到Optional当中贯彻是如此的5:

// Simplified implementation of Swift's Optional
enum MyOptional<T> {
  case Some(T)
  case None
}

此地有甚越发呢?注意枚举的关联值选拔泛型参数T作为自个儿类型,那样可选类型构造任何你想要的重返值。

枚举能够拥有三个泛型参数。就拿熟谙的Either类为例,它并非是Swift标准库中的一部分,而是实现于广大开源库以及
别的函数式编制程序语言,比如HaskellF#。设计想法是那样的:绝比较单纯再次来到三个值或尚未值(née
Optional),你更期待重返一个成功值也许部分申报音信(比如错误值)。

// The well-known either type is, of course, an enum that allows you to return either
// value one (say, a successful value) or value two (say an error) from a function
enum Either<T1, T2> {
  case Left(T1)
  case Right(T2)
}

最后,Swift中负有在classstruct中奏效的品类约束,在enum中一样适用。

// Totally nonsensical example. A bag that is either full (has an array with contents)
// or empty.
enum Bag<T: SequenceType where T.Generator.Element==Equatable> {
  case Empty
  case Full(contents: T)
}

Google翻译神坑,1和0频率相同翻译成0和0频率相同,喵喵喵?

递归 / 间接(Indirect)类型

直接类型是 斯维夫特 2.0 新增的2个种类。 它们允许将枚举中2个 case
的关联值再一次定义为枚举。举个例子,假如我们想定义2个文件系统,用来代表文件以及带有文件的目录。假若将文件目录概念为枚举的
case,则目录 case
的关联值应该再包涵二个文件的数组作为它的关系值。因为这是二个递归的操作,编写翻译器需求对此举办三个非正规的准备。Swift文书档案中是这么写的:

枚举和 case
可以被标记为间接的(indrect),那象征它们的关联值是被直接保存的,那允许大家定义递归的数据结构。

就此,倘诺我们要定义 FileNode 的枚举,它应有会是那样的:

enum FileNode {
  case File(name: String)
  indirect case Folder(name: String, files: [FileNode])
}

此处的 indrect 关键字告诉编写翻译器直接地处理那么些枚举的
case。也能够对全部枚举类型应用那一个至关心重视要字。用作例子,大家来定义2个二叉树:

indirect enum Tree<Element: Comparable> {
    case Empty
    case Node(Tree<Element>,Element,Tree<Element>)
}

那是一个很强劲的特征,可以让大家用十分简单的办法来定义一个装有复杂关系的数据结构。

把Case打成case被坑了一波。。对拍才意识QAQ

应用自定义类型作为枚举的值

如果大家忽视关联值,则枚举的值就只可以是整型,浮点型,字符串和布尔类型。假若想要协助其他类型,则足以由此落到实处
StringLiteralConvertible
协议来形成,这可以让大家因此对字符串的类别化和反种类化来使枚举支持自定义类型。

作为叁个例证,假若大家要定义一个枚举来保存不一致的 iOS 设备的显示屏尺寸:

enum Devices: CGSize {
   case iPhone3GS = CGSize(width: 320, height: 480)
   case iPhone5 = CGSize(width: 320, height: 568)
   case iPhone6 = CGSize(width: 375, height: 667)
   case iPhone6Plus = CGSize(width: 414, height: 736)
}

不过,那段代码无法经过编写翻译。因为 CGPoint
并不是贰个常量,不能够用来定义枚举的值。我们必要为想要帮助的自定义类型扩展3个恢弘,让其促成
StringLiteralConvertible
协议。那么些体协会议要求我们达成四个构造方法,那八个法子都须要接纳一个String品类的参数,并且大家需求将那一个字符串转换来大家须求的品种(此处是CGSize)。

extension CGSize: StringLiteralConvertible {
    public init(stringLiteral value: String) {
    let size = CGSizeFromString(value)
    self.init(width: size.width, height: size.height)
    }

    public init(extendedGraphemeClusterLiteral value: String) {
    let size = CGSizeFromString(value)
    self.init(width: size.width, height: size.height)
    }

    public init(unicodeScalarLiteral value: String) {
    let size = CGSizeFromString(value)
    self.init(width: size.width, height: size.height)
    }
}

未来就足以来达成大家要求的枚举了,不过那里有一个弱点:开头化的值必须写成字符串格局,因为那正是我们定义的枚举须要承受的门类(记住,我们兑现了
StringLiteralConvertible,因而String能够转化成CGSize类型)

enum Devices: CGSize {
   case iPhone3GS = "{320, 480}"
   case iPhone5 = "{320, 568}"
   case iPhone6 = "{375, 667}"
   case iPhone6Plus = "{414, 736}"
}

到头来,我们得以选拔 CGPoint 类型的枚举了。必要注意的是,当要赢得真实的
CGPoint 的值的时候,大家须要拜访枚举的是 rawValue 属性。

let a = Devices.iPhone5
let b = a.rawValue
print("the phone size string is \(a), width is \(b.width), height is \(b.height)")
// prints : the phone size string is iPhone5, width is 320.0, height is 568.0

动用字符串系列化的款式,会让动用自定义类型的枚举比较困难,但是在少数特定的意况下,那也会给大家扩展很多方便(比较使用NSColor
/
UIColor的时候)。不仅如此,大家一齐能够对自身定义的连串应用那个方法。

最好的做法是今后加0或然1
不用特判,不会炸整,往前加的话就要特判,然后小心开 long long
,要模四遍保障不会炸 (LLJ大佬说要开usinged long long ,因为 long long
只到2^64-1,实际那题只到2^63于是并非)

对枚举的关联值进行比较

在一般意况下,枚举是很不难进行相等性判断的。二个不难易行的
enum T { case a, b } 完成暗许辅助相等性判断 T.a == T.b, T.b != T.a

可是,一旦大家为枚举扩大了关乎值,Swift就从未艺术正确地为两个枚举举行相等性判断,要求大家温馨完结 ==
运营符。那并不是很勤奋:

enum Trade {
    case Buy(stock: String, amount: Int)
    case Sell(stock: String, amount: Int)
}
func ==(lhs: Trade, rhs: Trade) -> Bool {
   switch (lhs, rhs) {
     case let (.Buy(stock1, amount1), .Buy(stock2, amount2))
       where stock1 == stock2 && amount1 == amount2:
       return true
     case let (.Sell(stock1, amount1), .Sell(stock2, amount2))
       where stock1 == stock2 && amount1 == amount2:
       return true
     default: return false
   }
}

正如大家所见,我们经过 switch 语句对五个枚举的 case
进行判定,并且唯有当它们的 case 是协作的时候(比如 Buy 和
Buy)才对它们的实际关联值举办判定。

mobile.365-838.com 5mobile.365-838.com 6

自定义构造方法

静态方法
一节在那之中我们已经涉及它们得以看做从不相同数量构造枚举的惠及形式。在事先的事例里也显得过,对出版社常常误用的苹果设备名再次来到正确的名字:

enum Device { 
    case AppleWatch 
    static func fromSlang(term: String) -> Device? {
      if term == "iWatch" {
      return .AppleWatch
      }
      return nil
    }
}

大家也能够应用自定义构造方法来替换静态方法。枚举与结构体和类的构造方法最大的不一致在于,枚举的构造方法供给将隐式的
self 属性设置为不易的 case。

enum Device { 
    case AppleWatch 
    init?(term: String) {
      if term == "iWatch" {
      self = .AppleWatch
      }
      return nil
    }
}

在那个例子中,大家运用了可难倒(failable)的构造方法。可是,普通的构造方法也足以干活得很好:

enum NumberCategory {
   case Small
   case Medium
   case Big
   case Huge
   init(number n: Int) {
    if n < 10000 { self = .Small }
    else if n < 1000000 { self = .Medium }
    else if n < 100000000 { self = .Big }
    else { self = .Huge }
   }
}
let aNumber = NumberCategory(number: 100)
print(aNumber)
// prints: "Small"
//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
typedef unsigned long long LL;
const int maxn=100;
const int maxk=105;
int T,n,k;
LL dp[maxn][maxn][maxk],ans,ll=1; 
void work(){
    if(!k||n&1) {printf("0\n"); return;}
    memset(dp,0,sizeof(dp));
    dp[0][0][0]=1;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=i;j++) 
            for(int l=0;l<k;l++) {
               if(j) dp[i][j][(l+((ll=1)<<(i-1))%k)%k]+=dp[i-1][j-1][l];
               if(i!=n) dp[i][j][l]+=dp[i-1][j][l];
            }
    ans=0;
    printf("%llu\n",dp[n][n/2][0]);
}
int main()
{

    scanf("%d",&T);
    for(int i=1;i<=T;i++){
        scanf("%d%d",&n,&k);
        printf("Case %d: ",i);
        work(); 
    }
    return 0;
}

对枚举的 case 举办迭代

一个专门平常被问到的题材正是何等对枚举中的 case
实行迭代。可惜的是,枚举并不曾遵从SequenceType说道,因而并未2个合法的做法来对其进行迭代。取决于枚举的种类,对其进展迭代只怕也差不离,也有恐怕很困苦。在StackOverflow上有一个很好的研讨贴。贴子里面商量到的不比景况太多了,假若只在此间摘取一些会有片面性,而假诺将全部情况都列出来,则会太多。

View
Code

对 Objective-C 的支持

依照整型的枚举,如 enum Bit: Int { case Zero = 0; case One = 1 }
能够因而 @objc 标识来将其桥接到 Objective-C
个中。可是,一旦接纳整型之外的种类(如
String)或许初步运用关联值,大家就不能够在 Objective-C
个中使用这么些枚举了。

有三个名为_ObjectiveCBridgeable的隐藏协议,可以让业内大家以定义合适的情势,如此一来,斯威夫特便能够正确地将枚举转成 Objective-C
类型,但自笔者猜那么些体协会议被埋伏起来肯定是有案由的。可是,从理论上来讲,那几个协议恐怕允许大家将枚举(包蕴实际枚举值)正确地桥接到
Objective-C 个中。

唯独,大家并不一定非要使用方面提到的那么些措施。为枚举添加七个章程,使用
@objc
定义3个代表类型,如此一来我们便能够自由地将枚举进行转换了,并且那种艺术不供给服从私有协议:

enum Trade {
    case Buy(stock: String, amount: Int)
    case Sell(stock: String, amount: Int)
}

// 这个类型也可以定义在 Objective-C 的代码中
@objc class OTrade: NSObject {
    var type: Int
    var stock: String
    var amount: Int
    init(type: Int, stock: String, amount: Int) {
    self.type = type
    self.stock = stock
    self.amount = amount
    }
}

extension Trade  {

    func toObjc() -> OTrade {
    switch self {
    case let .Buy(stock, amount):
        return OTrade(type: 0, stock: stock, amount: amount)
    case let .Sell(stock, amount):
        return OTrade(type: 1, stock: stock, amount: amount)
    }
    }

    static func fromObjc(source: OTrade) -> Trade? {
    switch (source.type) {
    case 0: return Trade.Buy(stock: source.stock, amount: source.amount)
    case 1: return Trade.Sell(stock: source.stock, amount: source.amount)
    default: return nil
    }
    }
}

这一个主意有四个的后天不足,大家需求将枚举映射为 Objective-C 中的 NSObject
基础项目(大家也能够一向运用
NSDictionary),不过,当大家蒙受一些确实需要在 Objective-C
个中获取有关联值的枚举时,那是多少个足以利用的不二法门。

 

枚举底层

埃里克a Sadun
写过一篇很流弊的有关枚举底层的博客,涉及到枚举底层的上上下下。在生养代码中不用应该运用到这么些事物,可是读书一下照旧格外幽默的。在此地,作者准备只涉及那篇博客中一条,假若想打听更加多,请移步到原来的小说:

枚举平时都以3个字节长度。[…]假定您确实很傻很天真,你当然能够定义一个有不少个
case
的枚举,在那种状态下,取决于最少所须求的比特数,枚举大概占据三个字节也许越来越多。

那是今后加的版本

Swift 标准库中的枚举

在大家准备继续探索枚举在项目中的不一致用例从前,先看一下在 斯维夫特标准库个中是哪些使用枚举大概会更使人迷恋,所以未来让我们先来看望。

Bit
那一个枚举有多个值,OneZero。它被看做 CollectionOfOne<T>
中的 Index 类型。

FloatingPointClassification
这几个枚举定义了一文山会海 IEEE 754 恐怕的档次,比如 NegativeInfinity,
PositiveZeroSignalingNaN

Mirror.AncestorRepresentation

Mirror.DisplayStyle
那七个枚举被用在 斯威夫特 反射 API 的上下文个中。

Optional
这些就无须多说了

Process
这几个枚举包涵了近年来进程的命令行参数(Process.argc,
Process.arguments)。那是贰个一定幽默的枚举类型,因为在 Swift 1.0
当中,它是被用作一个组织体来完成的。

    for(int i=1;i<n;i++)
        for(int j=0;j<=i;j++) 
            for(int l=0;l<k;l++) {
               dp[i+1][j+1][((l<<1)|1)%k]+=dp[i][j][l];
               dp[i+1][j][(l<<1)%k]+=dp[i][j][l];
            }

实行用例

咱俩早就在前头多少个小节个中看过了成都百货上千可行的枚举类型。包蕴
OptionalEither, FileNode
还有二叉树。可是,还存在许多场子,使用枚举要胜过使用结构体和类。一般来讲,假使难点得以被诠释为不难的分歧档次,则选用枚举应该就是正确的挑选。即便只有两种case,那也是1个应用枚举的两半场景,正如 Optional 和 Either
类型所出示的。

以下列举了一部分枚举类型在实战中的使用示例,可以用来引燃你的创设力。

 

错误处理

说到枚举的进行应用,当然必不可少在 斯维夫特 2.0
在那之中新生产的错误处理。标记为可抛出的函数能够抛出任何坚守了 ErrorType
空协议的品类。正如 斯威夫特 官方文书档案中所写的:

Swift的枚举特别适用于营造一组有关的荒谬状态,能够因此关联值来为其扩张额外的附加消息。

用作一个演示,大家来看下流行的JSON解析框架
Argo
。当
JSON 解析失利的时候,它有恐怕是以下二种重点原因:

  1. JSON 数据不够有些最终模型所必要的键(比如你的模型有二个 username
    的性质,但是 JSON 中不够了)
  2. 存在项目不匹配,比如说 username 需求的是 String 类型,而 JSON
    中富含的是
    NSNull6

除了,Argo 还为不含有在上述七个品类中的错误提供了自定义错误。它们的
ErrorType 枚举是看似那样的:

enum DecodeError: ErrorType {
  case TypeMismatch(expected: String, actual: String)
  case MissingKey(String)
  case Custom(String)
}

富有的 case 都有3个关乎值用来含有关于错误的叠加新闻。

叁个特别通用的用于完整 HTTP / REST API
错误处理的ErrorType应该是类似那样的:

enum APIError : ErrorType {
    // Can't connect to the server (maybe offline?)
    case ConnectionError(error: NSError)
    // The server responded with a non 200 status code
    case ServerError(statusCode: Int, error: NSError)
    // We got no data (0 bytes) back from the server
    case NoDataError
    // The server response can't be converted from JSON to a Dictionary
    case JSONSerializationError(error: ErrorType)
    // The Argo decoding Failed
    case JSONMappingError(converstionError: DecodeError)
}

这个 ErrorType 完毕了整机的 REST
程序栈解析有可能出现的荒唐,包涵了拥有在分析结构体与类时碰面世的荒谬。

设若您看得够细致,会意识在JSONMappingError中,我们将Argo中的DecodeError装进到了大家的APIError项目个中,因为我们会用
Argo 来作实际的 JSON 解析。

越来越多关于ErrorType以及此种枚举类型的演示能够参考合法文书档案

4.

观望者形式

在 斯维夫特 其中,有许多办法来营造观望形式。假设利用 @objc
包容标记,则我们得以应用 NSNotificationCenter 或者
KVO。纵然无须这一个标记,didSet语法也得以很不难地贯彻简单的观测形式。在此处能够利用枚举,它能够使被观察者的转变尤为清晰明了。设想大家要对多个聚集实行观看。如若我们有个别思考一下就会意识那唯有两种恐怕的景色:七个或八个项被插入,二个或八个项被删除,2个或四个项被更新。那听起来就是枚举能够成功的办事:

enum Change {
     case Insertion(items: [Item])
     case Deletion(items: [Item])
     case Update(items: [Item])
}

其后,观望对象就可以选择八个很不难的主意来取得已经发生的作业的详细信息。那也得以经过为其扩张
oldValuenewValue 的简短方法来扩张它的意义。

UVA – 1628 Pizza
Delivery

状态码

设若大家正在利用多少个外部系统,而那些系统利用了状态码(大概错误码)来传递错误音信,类似
HTTP
状态码,那种情景下枚举正是一种很鲜明并且很好的措施来对信息进行包装7

enum HttpError: String {
  case Code400 = "Bad Request"
  case Code401 = "Unauthorized"
  case Code402 = "Payment Required"
  case Code403 = "Forbidden"
  case Code404 = "Not Found"
}

自作者爱记念化搜索,纪念化搜索最强。

结果类型映射(Map Result Types)

枚举也时时被用来将 JSON 解析后的结果映射成 Swift的原生类型。那里有2个简短的例证:

enum JSON {
    case JSONString(Swift.String)
    case JSONNumber(Double)
    case JSONObject([String : JSONValue])
    case JSONArray([JSONValue])
    case JSONBool(Bool)
    case JSONNull
}

就像地,假设大家分析了其他的事物,也能够行使那种措施将分析结果转化大家Swift 的门类。

dp[i][j][o][k]代表i到j的订单已处理好,未来在i恐怕j
还要送k家的最优解

UIKit 标识

枚举能够用来将字符串类型的任用标识可能 storyboard
标识映射为项目系统能够拓展自作者批评的门类。借使大家有五个拥有许多原型 Cell 的
UITableView:

enum CellType: String {
    case ButtonValueCell = "ButtonValueCell"
    case UnitEditCell = "UnitEditCell"
    case LabelCell = "LabelCell"
    case ResultLabelCell = "ResultLabelCell"
}

枚举,记忆化

单位

单位以及单位转换是另1个应用枚举的绝佳场馆。能够将单位会同相应的转换率映射起来,然后添加方法来对单位进行自动的转移。以下是多少个万分简单的示范:

enum Liquid: Float {
  case ml = 1.0
  case l = 1000.0
  func convert(amount amount: Float, to: Liquid) -> Float {
      if self.rawValue < to.rawValue {
     return (self.rawValue / to.rawValue) * amount
      } else {
     return (self.rawValue * to.rawValue) * amount
      }
  }
}
// Convert liters to milliliters
print (Liquid.l.convert(amount: 5, to: Liquid.ml))

另2个演示是通货的转换。以及数学符号(比如角度与弧度)也能够从中收益。

for(int i=1;i<l;i++) u=max(u,dfs(i,r,0,k-1)+e[i]-k*abs(p[i]-p[o==0?l:r]));
    for(int i=n;i>r;i--) u=max(u,dfs(l,i,1,k-1)+e[i]-k*abs(p[i]-p[o==0?l:r]));

游戏

打闹也是枚举中的另四个相当好的用例,显示屏上的绝超过二分一实体都属于3个特定种族的项目(仇人,障碍,纹理,…)。相对于本地的
iOS 恐怕 Mac
应用,游戏更像是四个白板。即开发娱乐大家能够利用全新的对象以及全新的涉嫌创建2个崭新的社会风气,而
iOS 也许 OSX 要求接纳预约义的 UIButtons,UITableViews,UITableViewCells
只怕 NSStackView.

不仅如此,由于枚举能够服从协议,大家能够运用协议扩充和依照协议的编制程序为不一样为游乐定义的枚举扩充效果。那里是三个用来展现那种层级的的简短示例:

enum FlyingBeast { case Dragon, Hippogriff, Gargoyle }
enum Horde { case Ork, Troll }
enum Player { case Mage, Warrior, Barbarian }
enum NPC { case Vendor, Blacksmith }
enum Element { case Tree, Fence, Stone }

protocol Hurtable {}
protocol Killable {}
protocol Flying {}
protocol Attacking {}
protocol Obstacle {}

extension FlyingBeast: Hurtable, Killable, Flying, Attacking {}
extension Horde: Hurtable, Killable, Attacking {}
extension Player: Hurtable, Obstacle {}
extension NPC: Hurtable {}
extension Element: Obstacle {}

留神这一段先搜两边再中间,能够达到规定的标准记念化效果

字符串类型化

在二个有点大学一年级点的 Xcode
项目中,大家相当的慢就会有一大堆通过字符串来走访的能源。在近日的小节中,我们早已提过重用标识和
storyboard
的标识,但是除此之外这两样,还存在很多能源:图像,Segues,Nibs,字体以及其余能源。平常情形下,那一个能源都得以分为分歧的聚众。就算是那样的话,3个类型化的字符串会是四个让编写翻译器帮我们开始展览项目检查的好点子。

enum DetailViewImages: String {
  case Background = "bg1.png"
  case Sidebar = "sbg.png"
  case ActionButton1 = "btn1_1.png"
  case ActionButton2 = "btn2_1.png"
}

对于 iOS
开发者,R.swift本条第叁方库可以为上述关联的状态自动生成结构体。不过多少时候你或然要求有更加多的主宰(可能您只怕是2个Mac开发者8)。

代码

API 端点

Rest API 是枚举的绝佳用例。它们都是分组的,它们都是有限的 API
集合,并且它们也说不定会有增大的询问也许命名的参数,而那能够运用关联值来兑现。

此处有个 Instagram
API

的简化版:

enum Instagram {
  enum Media {
    case Popular
    case Shortcode(id: String)
    case Search(lat: Float, min_timestamp: Int, lng: Float, max_timestamp: Int, distance: Int)
  }
  enum Users {
    case User(id: String)
    case Feed
    case Recent(id: String)
  }
}

Ash
Furrow的Moya框架
就是着力这些考虑,使用枚举对
rest 端点进行映射。

mobile.365-838.com 7mobile.365-838.com 8

链表

Airspeed
Velocity有一篇极好的稿子表达了什么接纳枚举来促成叁个链表。那篇小说中的大多数代码都不止了枚举的文化,并提到到了大气任何有趣的核心9,但是,链表最中心的定义是接近那样的(小编对其进展了有的简化):

enum List {
    case End
    indirect case Node(Int, next: List)
}

每3个节点(Node) case 都指向了下一个 case,
通过使用枚举而非别的项目,大家得以免止使用2个可选的 next
类型以用来表示链表的利落。

Airspeed Velocity 还写过一篇超赞的博客,关于如何利用 Swift的直接枚举类型来贯彻红黑树,所以要是您曾经阅读过有关链表的博客,你或许想继续阅读这篇有关红黑树的博客

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=100+5;
int T,now,dp[maxn][maxn][2][maxn],vis[maxn][maxn][2][maxn],n,p[maxn],e[maxn],ans;
int dfs(int l,int r,int o,int k) {
    if(k==0) return 0;
    if(vis[l][r][o][k]==now) return dp[l][r][o][k];
    vis[l][r][o][k]=now;
    int &u=dp[l][r][o][k];
    u=0;
    for(int i=1;i<l;i++) u=max(u,dfs(i,r,0,k-1)+e[i]-k*abs(p[i]-p[o==0?l:r]));
    for(int i=n;i>r;i--) u=max(u,dfs(l,i,1,k-1)+e[i]-k*abs(p[i]-p[o==0?l:r]));
    return u;  
}
int main()
{
    scanf("%d",&T);
    for(now=1;now<=T;now++) {
    ans=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&p[i]);
    for(int i=1;i<=n;i++) scanf("%d",&e[i]);
    for(int kk=1;kk<=n;kk++) 
        for(int i=1;i<=n;i++)
        ans=max(ans,dfs(i,i,0,kk-1)+e[i]-kk*abs(p[i]));
    printf("%d\n",ans); 
    }
    return 0;
}

设置字典(Setting Dictionaries)

这是 Erica Sadun
提出的相当尤其灵活的消除方案。一句话来说,正是别的大家供给用八个属性的字典来对3个项实行设置的时候,都应当使用一三种关于联值的枚举来顶替。使用那办法,类型检查体系能够保障布局的值都是不易的项目。

至于更加多的细节,以及方便的事例,能够阅读下她的篇章

View
Code

局限

与前边好像,小编将会用一密密麻麻枚举的局限性来收场本篇文章。

 

领取关联值

大卫Owens写过一篇文章,他觉得眼下的关联值提取方法是很笨重的。笔者墙裂推荐您去看一下她的原著,在此地本人对它的主旨举行下表达:为了从一个枚举中收获涉及值,大家亟须使用格局匹配。然则,关联值正是涉及在特定枚举
case 的快捷元组。而元组是足以行使更简约的方法来得到它在那之中值,即
.keyword 或者 .0

// Enums
enum Ex { case Mode(ab: Int, cd: Int) }
if case Ex.Mode(let ab, let cd) = Ex.Mode(ab: 4, cd: 5) {
    print(ab)
}
// vs tuples:
let tp = (ab: 4, cd: 5)
print(tp.ab)

倘诺您也同样以为大家相应使用同一的措施来对枚举进行解构(deconstruct),那里有个
rdar:
rdar://22704262
(译者注:一从头笔者不了然 rdar 是啥意思,后来自个儿 google
了下,若是您也有趣味,也足以友善去寻觅一下)

5.BZOJ 1009
[HNOI2008]GT考试

相等性

抱有关联值的枚举没有遵循 equatable
协议。那是一个不满,因为它为无数政工扩展了不须要的复杂和劳动。深层的缘由也许是因为关联值的底层使用是行使了元组,而元组并从未坚守
equatable 协议。不过,对于限制的 case
子集,假设那么些关联值的体系都遵守了 equatable
类型,笔者觉得编写翻译器应该暗许为其生成 equatable 扩展。

// Int 和 String 是可判等的, 所以 Mode 应该也是可判等的
enum Ex { case Mode(ab: Int, cd: String) }

// Swift 应该能够自动生成这个函数
func == (lhs: Ex.Mode, rhs: Ex.Mode) -> Bool {
    switch (lhs, rhs) {
       case (.Mode(let a, let b), .Mode(let c, let d)):
       return a == c && b == d
       default:
       return false
    }
}

一初始傻逼地kmp直接往前跳1个就停了,后来改了又调了绵绵发现自身Kmp写错了,贼难熬。。

元组(Tuples)

最大的标题正是对元组的协理。小编喜欢使用元组,它们得以使广大作业变得更简短,可是他们如今还地处无文书档案状态并且在众多场馆都不可能使用。在枚举当中,我们鞭长莫及利用元组作为枚举的值:

enum Devices: (intro: Int, name: String) {
  case iPhone = (intro: 2007, name: "iPhone")
  case AppleTV = (intro: 2006, name: "Apple TV")
  case AppleWatch = (intro: 2014, name: "Apple Watch")
}

那犹如看起来并不是二个最好的示范,可是我们假诺初步应用枚举,就会时常陷入到须求用到类似上边那些示例的境况中。

就kmp转移然后矩阵优化。

迭代枚举的有所case

本条大家早就在前面议论过了。方今还尚未一个很好的形式来赢得枚举中的全数case 的集纳以使大家可以对其开展迭代。

mobile.365-838.com 9mobile.365-838.com 10

私下认可关联值

另叁个会遭受的事是枚举的关联值总是类型,不过大家却一筹莫展为这几个体系钦定暗许值。就算有那样一种状态:

enum Characters {
  case Mage(health: Int = 70, magic: Int = 100, strength: Int = 30)
  case Warrior(health: Int = 100, magic: Int = 0, strength: Int = 100)
  case Neophyte(health: Int = 50, magic: Int = 20, strength: Int = 80)
}

大家依旧能够利用不相同的值成立新的 case,可是剧中人物的暗许设置依旧会被映射。

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
int ans,n,m,p,top,a[21],nxt[21],cnt[21],vis[11];
struct jz{
    int x[21][21];
    friend jz operator *(const jz&l,const jz&r){
         jz res;
         for(int i=0;i<21;i++)
         for(int j=0;j<21;j++)
         res.x[i][j]=0;
         for(int i=0;i<21;i++)
             for(int j=0;j<21;j++) {
                 for(int k=0;k<21;k++)
                     (res.x[i][j]+=(l.x[i][k]*r.x[k][j])%p)%=p;
             } 
         return res;
    }
}base,ret,tmp;
void input() {
    scanf("%d%d%d",&n,&m,&p);
    char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) a[++top]=ch-'0';
}
int make_nxt(int a[],int *nxt) {
    for (int j=0,i=2;i<=m;i++) {
        while (j&&a[j+1]!=a[i]) j=nxt[j];
        if (a[j+1]==a[i]) j++;
        nxt[i]=j;
     }
}
void ksm(int b){
    while(b){
        if(b&1) ret=ret*base;
        base=base*base;
        b>>=1;
    }
}
void work() {
    for(int i=0;i<m;i++) { 
        cnt[i]++; 
        vis[a[i+1]]=i+1;
        if(i+1!=m) {base.x[i][i+1]++;}
        int tp=i;
        while(nxt[tp]) {
            tp=nxt[tp];
            if(vis[a[tp+1]]!=i+1) {
            vis[a[tp+1]]=i+1;
            cnt[i]++;
            base.x[i][tp+1]++;
            }
        }
        if(vis[a[1]]!=i+1) {
            cnt[i]++;
            base.x[i][1]++;
        }
        base.x[i][0]+=(10-cnt[i]);
    } 
    for(int i=0;i<m;i++)
        for(int j=0;j<m;j++) 
            if(i==j) ret.x[i][j]=1;
    ksm(n);
    ans=0;
    for(int i=0;i<m;i++) 
    (ans+=ret.x[0][i])%=p;
    printf("%d\n",ans);
}
int main()
{
    input();
    make_nxt(a,nxt);
    work();
    return 0;
}

变化

GT考试

10/26/2015

  • 追加局限性示例(相等性 & 获取关联值)
  • 扩展 埃里克a Sadun 的关联枚举示例

 

10/22/2015

  • 合并来自 #6
    @mabidakun
    的PR
  • 日增枚举底层的链接
  • 将帐号示例拆分为多个更便于明白的一些。

6.BZOJ 1855
[SCOI2010]股票交易

10/21/2015

在某位学长的博客里看看那题第③句话是省选怎么会考这么不难的题呢,然后就发现自身不会做。。。

解释

<a name=”c1″></a>

  • ① 、能够利用部分小技巧来完毕这么些指标,具体的请参见上面包车型地铁小说内容
    <a name=”c2″></a>

  • 二 、为了演示的来头,那几个示例的完毕经过的简化。在实际的开销中,应该运用可选类型以及反向顺序的参数。可以参见一下现行反革命格外风行的函数式编制程序库,如
    Swiftz

    Dollar
    <a name=”c3″></a>

  • 3、这么些示例直接使用了斯威夫特官方文书档案的以身作则
    <a name=”c4″></a>

  • ④ 、平时使得他们定义的职位很难被发觉
    <a name=”c5″></a>

  • 伍 、那是3个简化版的,当然,斯威夫特 为大家加了广大的语法糖
    <a name=”c6″></a>

  • 陆 、倘若您在接纳中选择过 JSON,应该也早就遭逢过这些题材
    <a name=”c6″></a>

  • 七 、顺便一提,不可能直接利用数字做为枚举 case 的名目,因而平素选用 400
    是11分的
    <a name=”c8″></a>

  • 捌 、纵然如此,不过扶助 Mac 版的 瑞鹰.swift 好像就快生产了
    <a name=”c9″></a>

  • 9、那句话能够解释为: 打开链接,并早先阅读文章

神奇的枯燥队列优化,只怕是自笔者单调队列写得太少了。。

很简单领悟景况dp[i][j]意味着时间为i手中股票为j的最大收益,早先化为相当的小值,dp[0][0]=0;

下一场转移分二种

不买不卖:dp[i][j]=max(dp[i][j],dp[i-1][j]);

买入:dp[i][j]=max(dp[i][j],dp[i-w-1][j-k]-k*ap[i]);

卖出:dp[i][j]=max(dp[i][j],dp[i-w-1][j+k]+k*bp[i]);

下一场大家发现后七个枚举k会超时,就把它优化一下
(其实自个儿也。。相比懵逼)

买入:dp[i][j]=max(dp[i][j],dp[i-w-1][k]-(j-k)*ap[i]);

                   
=max(dp[i][j],(dp[i-w-1][k]+k*ap[i])-j*ap[i]);

卖出:dp[i][j]=max(dp[i][j],dp[i-w-1][k]+(k-j)*bp[i]);

                   
 =max(dp[i][j],(dp[i-w-1][k]+k*ap[i])-j*bp[i]);

以购买为例,我们发现 这一某些dp[i-w-1][k]+k*ap[i]
(j-k>0,j-k<as[i])具有单调性,

                   k>j-as[i]
大家枚举k,然后丢进单调队列, 更新现在的dp[i][k];

mobile.365-838.com 11mobile.365-838.com 12

//Twenty
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=2000+299; 
int ans,n,maxp,w,dp[maxn][maxn];
int ap[maxn],bp[maxn],as[maxn],bs[maxn],que[maxn],ql=1,qr;
int main()
{
    scanf("%d%d%d",&n,&maxp,&w);
    for(int i=1;i<=n;i++) 
    scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
    memset(dp,128,sizeof(dp));
    dp[0][0]=0;
    for(int i=1;i<=n;i++) {
        ql=1,qr=0;
        for(int j=0;j<=maxp;j++) {
            dp[i][j]=max(dp[i][j],dp[i-1][j]);
            if(i-w-1>0) {
                while(ql<=qr&&que[ql]<j-as[i]) ql++;
                while(ql<=qr&&dp[i-w-1][que[qr]]+que[qr]*ap[i]-j*ap[i]<=dp[i-w-1][j]) qr--;
                que[++qr]=j;
                if(ql<=qr) dp[i][j]=max(dp[i][j],dp[i-w-1][que[ql]]+que[ql]*ap[i]-j*ap[i]);
            }
            else if(j<=as[i]) dp[i][j]=max(dp[i][j],-ap[i]*j);
        }
        ql=1,qr=0;
        for(int j=maxp;j>=0;j--) {
           if(i-w-1>0){
               while(ql<=qr&&que[ql]>j+bs[i]) ql++;
               while(ql<=qr&&dp[i-w-1][que[qr]]+que[qr]*bp[i]-j*bp[i]<=dp[i-w-1][j]) qr--;
               que[++qr]=j;
               if(ql<=qr) dp[i][j]=max(dp[i][j],dp[i-w-1][que[ql]]+que[ql]*bp[i]-j*bp[i]);
           }
        }
    }
    for(int i=0;i<=maxp;i++) ans=max(ans,dp[n][i]);
    printf("%d\n",ans);
    return 0;
}

股票交易

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 mobile.365-838.com 版权所有