Return to problem list2018-1B Problem C
Wrong solution
func start() {
}
type Metal struct {
ing1, ing2 int
hasAmount uint
}
var metals []Metal
var totalSupply uint
func test() {
var M int
mustReadLineOfInts(&M)
metals = make([]Metal, M)
for i := 0; i < M; i++ {
var ing1, ing2 int
mustReadLineOfInts(&ing1, &ing2)
metals[i].ing1 = ing1 - 1
metals[i].ing2 = ing2 - 1
}
line := strings.Split(mustReadLine(), " ")
assert(len(line) == M)
for i := 0; i < M; i++ {
ps, err := strconv.ParseUint(line[i], 10, 32)
if err != nil {
panic(err)
}
metals[i].hasAmount = uint(ps)
totalSupply += metals[i].hasAmount
}
var l, r uint
r = totalSupply + 1
for r-l > 1 {
m := (l + r) / 2
if check(m) {
l = m
} else {
r = m
}
}
fmt.Fprintf(stdout, "%d\n", l)
}
func check(m uint) bool {
wants := make(map[int]uint)
wants[0] = m
totalWanted := m
for {
unsatisfied := -1
for want, amount := range wants {
if metals[want].hasAmount < amount {
unsatisfied = want
break
} else {
metals[want].hasAmount -= amount
delete(wants, want)
}
}
if unsatisfied == -1 {
return true
}
additionalWantedAmount := wants[unsatisfied] - metals[unsatisfied].hasAmount
assert(additionalWantedAmount > 0)
wants[unsatisfied] = wants[unsatisfied] - additionalWantedAmount
if wants[unsatisfied] == 0 {
delete(wants, unsatisfied)
}
wants[metals[unsatisfied].ing1] += additionalWantedAmount
wants[metals[unsatisfied].ing2] += additionalWantedAmount
totalWanted += additionalWantedAmount
if totalWanted > totalSupply {
return false
}
}
}
Solution that only works for the small input
func start() {
}
type Metal struct {
ing1, ing2 int
hasAmount uint
}
var metals []Metal
func test() {
var M int
mustReadLineOfInts(&M)
metals = make([]Metal, M)
for i := 0; i < M; i++ {
var ing1, ing2 int
mustReadLineOfInts(&ing1, &ing2)
metals[i].ing1 = ing1 - 1
metals[i].ing2 = ing2 - 1
}
hasAmounts := mustReadLineOfIntsIntoArray()
assert(len(hasAmounts) == M)
for i := 0; i < M; i++ {
metals[i].hasAmount = uint(hasAmounts[i])
}
collectedZeroMetals := 0
for {
has := takeMetal(0, 0)
if has {
collectedZeroMetals++
} else {
break
}
}
fmt.Fprintf(stdout, "%d\n", collectedZeroMetals)
}
type ExclusionList map[int]bool
func takeMetal(metal int, depth int) bool {
target := &metals[metal]
if target.hasAmount > 0 {
target.hasAmount--
return true
}
if depth > len(metals) {
return false
}
tookIg1 := takeMetal(target.ing1, depth+1)
tookIg2 := takeMetal(target.ing2, depth+1)
if tookIg1 && tookIg2 {
return true
}
if tookIg1 {
metals[target.ing1].hasAmount++
}
if tookIg2 {
metals[target.ing2].hasAmount++
}
return false
}
func start() {
}
type Metal struct {
ing1, ing2 int
hasAmount uint
}
var metals []Metal
func test() {
var M int
mustReadLineOfInts(&M)
metals = make([]Metal, M)
for i := 0; i < M; i++ {
var ing1, ing2 int
mustReadLineOfInts(&ing1, &ing2)
metals[i].ing1 = ing1 - 1
metals[i].ing2 = ing2 - 1
}
line := strings.Split(mustReadLine(), " ")
assert(len(line) == M)
var totalAmountHas uint = 0
for i := 0; i < M; i++ {
ps, err := strconv.ParseUint(line[i], 10, 32)
if err != nil {
panic(err)
}
metals[i].hasAmount = uint(ps)
totalAmountHas += metals[i].hasAmount
}
recipe := make(map[int]uint)
recipe[0] = 1
var zeroMetalsProduced uint
a:
for {
limitingMetals := make([]int, 0)
var produceAmount uint = (1 << 32) - 1
var totalNumRequired uint = 0
for metalRequired, amountRequired := range recipe {
totalNumRequired += amountRequired
hasAmount := metals[metalRequired].hasAmount
if hasAmount < amountRequired {
limitingMetals = append(limitingMetals, metalRequired)
produceAmount = 0
} else {
canProduceAmount := hasAmount / amountRequired
if canProduceAmount < produceAmount {
produceAmount = canProduceAmount
}
}
}
if totalNumRequired > totalAmountHas {
break
}
if produceAmount == 0 {
for _, mtLacking := range limitingMetals {
metalLacking := metals[mtLacking]
hasAmount := metalLacking.hasAmount
additionalRequiredAmount := recipe[mtLacking] - hasAmount
if hasAmount == 0 {
delete(recipe, mtLacking)
} else {
recipe[mtLacking] = hasAmount
}
if metalLacking.ing1 == mtLacking {
break a
} else {
recipe[metalLacking.ing1] += additionalRequiredAmount
}
if metalLacking.ing2 == mtLacking {
break a
} else {
recipe[metalLacking.ing2] += additionalRequiredAmount
}
}
} else {
for metalRequired, amountRequired := range recipe {
deduction := amountRequired * produceAmount
assert(metals[metalRequired].hasAmount >= deduction)
metals[metalRequired].hasAmount -= deduction
totalAmountHas -= deduction
assert(totalAmountHas >= 0)
}
zeroMetalsProduced += produceAmount
}
}
fmt.Fprintf(stdout, "%d\n", zeroMetalsProduced)
}
func start() {
}
type Metal struct {
ing1, ing2 int
hasAmount uint
}
var metals []Metal
var totalSupply uint
func test() {
var M int
mustReadLineOfInts(&M)
metals = make([]Metal, M)
for i := 0; i < M; i++ {
var ing1, ing2 int
mustReadLineOfInts(&ing1, &ing2)
metals[i].ing1 = ing1 - 1
metals[i].ing2 = ing2 - 1
}
line := strings.Split(mustReadLine(), " ")
assert(len(line) == M)
for i := 0; i < M; i++ {
ps, err := strconv.ParseUint(line[i], 10, 32)
if err != nil {
panic(err)
}
metals[i].hasAmount = uint(ps)
totalSupply += metals[i].hasAmount
}
var l, r uint
r = totalSupply + 1
for r-l > 1 {
m := (l + r) / 2
if check(m) {
l = m
} else {
r = m
}
}
fmt.Fprintf(stdout, "%d\n", l)
}
func check(m uint) bool {
want := make(map[int]uint)
want[0] = m
totalWanted := m
for {
unsatisfied := -1
for want, amount := range want {
if metals[want].hasAmount < amount {
unsatisfied = want
break
}
}
if unsatisfied == -1 {
return true
}
additionalWantedAmount := want[unsatisfied] - metals[unsatisfied].hasAmount
assert(additionalWantedAmount > 0)
want[unsatisfied] = want[unsatisfied] - additionalWantedAmount
want[metals[unsatisfied].ing1] += additionalWantedAmount
want[metals[unsatisfied].ing2] += additionalWantedAmount
totalWanted += additionalWantedAmount
if totalWanted > totalSupply {
return false
}
}
}
Sample test cases given in question
3
3
2 3
1 3
1 2
5 2 3
5
3 4
3 4
4 5
3 5
1 3
0 8 6 2 4
4
3 4
2 3
2 3
2 3
0 1 1 0
Other files
@@ -92,18 +92,23 @@
}
if produceAmount == 0 {
for _, mtLacking := range limitingMetals {
- requiredAmount := recipe[mtLacking]
- delete(recipe, mtLacking)
metalLacking := metals[mtLacking]
+ hasAmount := metalLacking.hasAmount
+ additionalRequiredAmount := recipe[mtLacking] - hasAmount
+ if hasAmount == 0 {
+ delete(recipe, mtLacking)
+ } else {
+ recipe[mtLacking] = hasAmount
+ }
if metalLacking.ing1 == mtLacking {
break a
} else {
- recipe[metalLacking.ing1] += requiredAmount
+ recipe[metalLacking.ing1] += additionalRequiredAmount
}
if metalLacking.ing2 == mtLacking {
break a
} else {
- recipe[metalLacking.ing2] += requiredAmount
+ recipe[metalLacking.ing2] += additionalRequiredAmount
}
}
} else {