diff --git a/hw1/ZhongyiNi/answer.md b/hw1/ZhongyiNi/answer.md new file mode 100644 index 0000000..782eac0 --- /dev/null +++ b/hw1/ZhongyiNi/answer.md @@ -0,0 +1,31 @@ +## 9.6 +Follow the hints, we can easily get a $O(l^2v_{max})$ algorithm. But $v_{max}$ can be exponentially large with respect to the input size. Therefore, this will not imply P=NP. + +## 9.7 +Let $S$ denote the optimal set. +$$ + v = \sum_{i \in S} v_i +$$ +Let $S'$ denote the optimal set of problem $[v_i/K]$. +$$ +v' = \sum_{i \in S'} v_i +$$ +We have $v' \leq v$ and +$$ +\sum_{i \in S} [\frac{v_i}{K}] \leq \sum_{i \in S'} [\frac{v_i}{K}] +$$ +Since +$$ +x-1 < [x] \leq x +$$ +we have +$$ +v/K-|S|=\sum_{i \in S} \frac{v_i}{K} - |S|<\sum_{i \in S} [\frac{v_i}{K}] \leq \sum_{i \in S'} [\frac{v_i}{K}]\leq \sum_{i \in S'} \frac{v_i}{K} = v'/K +$$ + +Thus, +$$ +\frac{v'}{v} > 1 - K|S|/v > 1 - Kl/v +$$ + +I don't know how to decide $K$ with respect to $\epsilon$. \ No newline at end of file diff --git a/hw1/ZhongyiNi/dp.jl b/hw1/ZhongyiNi/dp.jl new file mode 100644 index 0000000..b7b6ded --- /dev/null +++ b/hw1/ZhongyiNi/dp.jl @@ -0,0 +1,65 @@ +struct Knapsack{T<:Integer} + W::T + w::Vector{T} + v::Vector{T} +end + +function dp(kp::Knapsack{T}) where T + l = length(kp.w) + vmax = maximum(kp.v) + wbound = sum(kp.w)+1 + @assert l == length(kp.v) + Sw = zeros(T,l,l*vmax) + Sset = Matrix{Vector{Int}}(undef,l,l*vmax) + for v in 1:l*vmax + for j in l:(-1):1 + if j == l + if kp.v[j] == v + Sw[j,v] = kp.w[j] + Sset[j,v] = [j] + else + Sw[j,v] = wbound + Sset[j,v] = Int[] + end + else + if v - kp.v[j] < 0 + Sw[j,v] = Sw[j+1,v] + Sset[j,v] = Sset[j+1,v] + else + if v == kp.v[j] + w_temp = kp.w[j] + set_temp = [j] + else + w_temp = kp.w[j] + Sw[j+1,v - kp.v[j]] + set_temp = [j] ∪ Sset[j+1,v - kp.v[j]] + end + if w_temp < Sw[j+1,v] + Sw[j,v] = w_temp + Sset[j,v] = set_temp + else + Sw[j,v] = Sw[j+1,v] + Sset[j,v] = Sset[j+1,v] + end + end + end + end + end + W = min(kp.W, wbound-1) + pos = findfirst(i->Sw[1,i] <= W ,l*vmax:(-1):1) + if isnothing(pos) + return zero(T),Int[] + else + optv = l*vmax-pos+1 + return Sw[1,optv],Sset[1,optv],optv + end +end + +function rescale_kp(kp::Knapsack{T},K) where T + return Knapsack(kp.W,kp.w,floor.(T,kp.v ./ K)) +end + +function _rescale_dp(kp::Knapsack,K) + kp2 = rescale_kp(kp,K) + w,set,_ = dp(kp2) + return w,set,sum(i -> kp.v[i], set) +end \ No newline at end of file diff --git a/hw1/ZhongyiNi/dptest.jl b/hw1/ZhongyiNi/dptest.jl new file mode 100644 index 0000000..25a0e7a --- /dev/null +++ b/hw1/ZhongyiNi/dptest.jl @@ -0,0 +1,26 @@ +using Test +include("dp.jl") + +@testset "testdp" begin + kp = Knapsack(10,[1,2,3,4,5],[2,3,4,5,6]) + w,set,optv = dp(kp) + @test w == 10 + @test set == [1,2,3,4] + @test optv == 14 +end + +@testset "rescale_kp" begin + kp = Knapsack(10,[1,2,3,4,5],[23,34,47,58,69]) + K = 10 + kp2 = rescale_kp(kp,K) + @test kp2.v == [2,3,4,5,6] +end + +@testset "rescale_dp" begin + kp = Knapsack(10,[1,2,3,4,5],[23,34,47,58,69]) + K = 10 + w,set,optv = _rescale_dp(kp,K) + @test w == 10 + @test set == [1,2,3,4] + @test optv == 162 +end