एक इलेक्ट्रिकल ग्रिड बनाएँ


22

चुनौती

एक सीधी रेखा में संरेखित एन शहर हैं। I-th शहर A[i]उत्पत्ति के दाईं ओर किलोमीटर की दूरी पर स्थित है। कोई भी दो शहर एक ही जगह नहीं होंगे।

आप कुछ बिजली संयंत्रों के साथ एक विद्युत ग्रिड का निर्माण करने जा रहे हैं। एक शहर के अंदर बिजली संयंत्र बनाए जाने चाहिए। हालाँकि, आपको केवल K(<N) पावर प्लांट बनाने की अनुमति है , इसलिए कुछ शहर ऐसे होंगे, जिनमें पावर प्लांट नहीं होंगे। बिना बिजली संयंत्रों वाले प्रत्येक शहर के लिए, आपको इसके और निकटतम शहर के बीच एक केबल का निर्माण करना होगा जिसमें एक बिजली संयंत्र हो

उदाहरण के लिए, अगर वहाँ तीन में स्थित शहर हैं 0, 1, 2, और केवल शहर में 0एक बिजली संयंत्र है, तो आप दो केबल, से एक का निर्माण करने की आवश्यकता 2करने के लिए 0से (2 किमी) और अन्य 1के लिए 0(1km) है, जो 3 किमी की कुल लंबाई है ।

Kशहरों को देखते हुए और पदों पर A, आपको ग्रिड बनाने के लिए आवश्यक न्यूनतम किलोमीटर केबल की गणना करनी चाहिए।

उदाहरण Testcases

K = 1, A = [0, 2, 4, 6, 8] : 12 
# build power plant in the city at position 4, total length = 4 + 2 + 0 + 2 + 4 = 12

K = 3, A = [0, 1, 10, 11, 20, 21, 22, 30, 32] : 23
# build power plants in cities at positions 0, 10 and 22

K = 5, A = [0, 1, 3, 6, 8, 11, 14] : 3
# build power plants in all cities except those at positions 0, 3

K = 6, A = [0, 1, 3, 6, 8, 14, 15, 18, 29, 30, 38, 41, 45, 46, 49, 58, 66, 72, 83, 84] : 49

विशेष विवरण

  • आपको एक फ़ंक्शन या प्रोग्राम लागू करना चाहिए, जो किसी भी रूप में Kएक पूर्णांक और पूर्णांक की एक सूची लेता है A, और उत्तर का प्रतिनिधित्व करने वाले पूर्णांक को आउटपुट / वापस करता है।

  • A आरोही क्रम में क्रमबद्ध है, और सभी तत्व गैर-नकारात्मक पूर्णांक हैं।

  • A[0] = 0, और A[N-1]1000N से अधिक नहीं होगा।

  • ध्यान दें कि आउटपुट 1000N 2 की परिमाण में होगा , इसलिए बड़े मामलों में, आपको कुछ भाषाओं में 64-बिट पूर्णांक की आवश्यकता हो सकती है।

  • मल्टीथ्रेडिंग की अनुमति नहीं है (मैं आपके प्रोग्राम की आत्मीयता को न्याय करते समय केवल 1 कोर पर सेट करूँगा)। संकलक अनुकूलन (जैसे -O2C) की अनुमति है।

स्कोरिंग

  • मैं आपके कंप्यूटर पर आपके कोड को (Ubuntu 16.04 Intel i7-3770S प्रोसेसर के साथ) अलग-अलग आकार के टेस्टकेस के साथ भेजूंगा। विशेष रूप से, मैं N = मंजिल (2 x / 5 ) के साथ कुछ टेस्टकेस उत्पन्न करूंगा जहां x एक सकारात्मक पूर्णांक है।
    आपका स्कोर सबसे छोटा टेस्टकेस का x मान होगा जिसे आपका प्रोग्राम 10 सेकंड या 1 GiB से अधिक मेमोरी का उपयोग करता है, या एक सही उत्तर नहीं देता है।

    • उच्चतम स्कोर जीत के साथ जवाब। यदि दो उत्तरों में समान स्कोर मिलता है, तो पहले वाला उत्तर जीत जाता है।
  • सभी कार्यक्रमों को टेस्टकेस के एक ही सेट द्वारा आंका जाएगा।

  • बेझिझक अपनी खुद की स्कोरिंग पोस्ट करें। आपके एल्गोरिथ्म के स्पष्टीकरण को प्रोत्साहित किया जाता है।

बोनस

यह मेरा C ++ प्रोग्राम है, यह 108 स्कोर करता है । आप 9a87fa183bad1e3a83d2df326682598796a216b3a4262c32f71dfb06df12935dलिंक में पूरे कोड खंड (बिना पाद लेख) द्वारा SHA-256 डाइजेस्ट को सत्यापित कर सकते हैं ।

एल्गोरिथ्म बाइनरी सर्च और नेउथ के अनुकूलन को जोड़ती है ताकि वांछित संख्या प्राप्त करने के लिए प्रत्येक पौधे का सही दंड मिल सके। जटिलता हे (एन लॉग एन लॉग ए [एन -1])। मुझे आश्चर्य हुआ कि कार्यक्रम को एंडर्स केसेर्ग द्वारा ओ (एन लॉग ए [एन) 1]) समाधान की तुलना में अधिक अंक मिला । यह शायद इस तथ्य के कारण है कि नूथ के अनुकूलन में लॉग केस आमतौर पर नहीं होगा।

ध्यान दें कि यह चुनौती IOI 2000 डाकघर के समान है । मूल बाधाएं एन <= 300 और के <= 30 हैं, हालांकि।


2^^(x/5): मातलब क्या है ? क्या आप सिर्फ N के लिए एक ऊपरी सीमा प्रदान कर सकते हैं?
Setop

1
@ सेटटॉप उदाहरण के लिए, यदि आपका प्रोग्राम N=21( = floor(2^(22/5)) )10 सेकंड में निपट सकता है , लेकिन सौदा नहीं कर सकता है N=24( = floor(2^(23/5)) ), तो 23 स्कोर होगा। मैंने ऊपरी बाउंड का उपयोग नहीं किया, क्योंकि विभिन्न एल्गोरिदम के बीच अंतर बहुत बढ़िया हैं। उदाहरण के लिए, अगर मैं एन सेट <= 40 है, वहाँ के बीच थोड़ा अंतर हो जाएगा O(KN^2)और O(KN^3), फिर भी O(2^N)यहां तक कि सस्ती समय में पूरी नहीं होगी।
कोलेरा सु

5
यह बहुत कुछ है जो मैं जीने के लिए करता हूं, और मैं आपको यह बता सकता हूं: यह वैसा नहीं है जैसा हम इलेक्ट्रिकल ग्रिड को डिजाइन करते हैं!
स्टीवी ग्रिफिन


3
उत्कृष्ट चुनौती, उत्कृष्ट स्कोरिंग प्रणाली। बहुत बढ़िया!
isaacg

जवाबों:


9

जंग , स्कोर = 104

यह Grønlund et al द्वारा नोट किए गए एल्गोरिदम का एक कार्यान्वयन है (2017) §3.3.1 के अंत में, हालांकि मुझे एक लंबी उद्धरण श्रृंखला का पालन करना था और कुछ लापता विवरण भरना था। यह ( एन लॉग [ एन - 1]) समय में चलता है ।

के साथ संकलित करें rustc -O। इनपुट फॉर्मेट Kपहली पंक्ति में है, इसके बाद Aएंट्री, प्रत्येक लाइन में एक प्रविष्टि, सभी स्टड पर।

(नोट: मैं इनाम की समय सीमा के एक घंटे बाद यह जमा कर रहा हूं, लेकिन मुझे उम्मीद है कि आखिरी समय में मैंने बाउंटी समय सीमा से पहले जमा किया था , जो ( एन लॉग एन लॉग [ एन - 1]) समय में चला था, लगभग ९ १ ।)

use std::cmp::min;
use std::io::{self, BufRead};
use std::iter::{once, Cloned};
use std::num::Wrapping;
use std::ops::Range;
use std::slice;
use std::time::Instant;
use std::u64;

type Cost = u64;
const INF: Cost = u64::MAX;

trait ColsTrait<Col>: Clone {
    type Iter: Iterator<Item = Col>;
    fn len(&self) -> usize;
    fn iter(&self) -> Self::Iter;
    fn slice(&self, range: Range<usize>) -> Self;
}

impl<'a, Col: Clone> ColsTrait<Col> for &'a [Col] {
    type Iter = Cloned<slice::Iter<'a, Col>>;
    fn len(&self) -> usize {
        (*self).len()
    }
    fn iter(&self) -> Self::Iter {
        (*self).iter().cloned()
    }
    fn slice(&self, range: Range<usize>) -> Self {
        unsafe { self.get_unchecked(range) }
    }
}

impl ColsTrait<usize> for Range<usize> {
    type Iter = Range<usize>;
    fn len(&self) -> usize {
        self.end - self.start
    }
    fn iter(&self) -> Range<usize> {
        self.clone()
    }
    fn slice(&self, range: Range<usize>) -> Self {
        Range {
            start: self.start + range.start,
            end: self.start + range.end,
        }
    }
}

fn smawk<Col: Copy, Cols: ColsTrait<Col>, Key: Ord, F: Copy + Fn(usize, Col) -> Key>(
    n: usize,
    shift: u32,
    cols: Cols,
    f: F,
) -> Vec<usize> {
    if n == 0 {
        Vec::new()
    } else if cols.len() > n {
        let mut s = Vec::with_capacity(n);
        let mut sk = Vec::with_capacity(n);
        for (jk, j) in cols.iter().enumerate() {
            while match s.last() {
                Some(&l) => f(!(!(s.len() - 1) << shift), j) <= f(!(!(s.len() - 1) << shift), l),
                None => false,
            } {
                s.pop();
                sk.pop();
            }
            if s.len() < n {
                s.push(j);
                sk.push(jk);
            }
        }
        smawk1(
            n,
            shift,
            cols,
            f,
            smawk(n / 2, shift + 1, &s[..], f)
                .into_iter()
                .map(|h| unsafe { *sk.get_unchecked(h) }),
        )
    } else {
        smawk1(
            n,
            shift,
            cols.clone(),
            f,
            smawk(n / 2, shift + 1, cols, f).into_iter(),
        )
    }
}

fn smawk1<
    Col: Copy,
    Cols: ColsTrait<Col>,
    Key: Ord,
    F: Fn(usize, Col) -> Key,
    Iter: Iterator<Item = usize>,
>(
    n: usize,
    shift: u32,
    cols: Cols,
    f: F,
    iter: Iter,
) -> Vec<usize> {
    let mut out = Vec::with_capacity(n);
    let mut range = 0..0;
    for (i, k) in iter.enumerate() {
        range.end = k + 1;
        out.push(
            range
                .clone()
                .zip(cols.slice(range.clone()).iter())
                .min_by_key(|&(_, col)| f(!(!(2 * i) << shift), col))
                .unwrap()
                .0,
        );
        out.push(k);
        range.start = k;
    }
    if n % 2 == 1 {
        range.end = cols.len();
        out.push(
            range
                .clone()
                .zip(cols.slice(range.clone()).iter())
                .min_by_key(|&(_, col)| f(!(!(n - 1) << shift), col))
                .unwrap()
                .0,
        );
    }
    out
}

fn solve(k: usize, a: &[Cost]) -> Cost {
    if k >= a.len() {
        return 0;
    }
    let sa = once(Wrapping(0))
        .chain(a.iter().scan(Wrapping(0), |s, &x| {
            *s += Wrapping(x);
            Some(*s)
        }))
        .collect::<Vec<_>>();
    let c = |i: usize, j: usize| {
        let h = (i - j) / 2;
        unsafe {
            (sa.get_unchecked(i) - sa.get_unchecked(i - h) - sa.get_unchecked(j + h)
                + sa.get_unchecked(j))
                .0
        }
    };
    let cost1 = c(a.len(), 0);
    if k == 1 {
        return cost1;
    }
    let cost2 = (1..a.len()).map(|j| c(j, 0) + c(a.len(), j)).min().unwrap();
    let mut low = 0;
    let mut high = cost1 - cost2;
    let mut ret = INF;
    while low <= high {
        let penalty = low + (high - low) / 2;
        let mut out = vec![(INF, 0); a.len() + 1];
        out[0] = (0, 0);
        let mut begin = 0;
        let mut chunk = 1;
        loop {
            let r = min(a.len() + 1 - begin, 2 * chunk);
            let edge = begin + chunk;
            let (out0, out1) = out.split_at_mut(edge);
            let f = |i: usize, j: usize| {
                let h = (edge + i - j) / 2;
                let &(cost, count) = unsafe { out0.get_unchecked(j) };
                (
                    cost.saturating_add(
                        unsafe {
                            sa.get_unchecked(edge + i) - sa.get_unchecked(edge + i - h)
                                - sa.get_unchecked(j + h)
                                + sa.get_unchecked(j)
                        }.0 + penalty,
                    ),
                    count + 1,
                )
            };
            for ((i, j), o) in smawk(r - chunk, 0, begin..edge, &f)
                .into_iter()
                .enumerate()
                .zip(out1.iter_mut())
            {
                *o = min(f(i, begin + j), *o);
            }
            let x = unsafe { out1.get_unchecked(r - 1 - chunk) };
            if let Some(j) = (edge..begin + r - 1).find(|&j| &f(r - 1 - chunk, j) <= x) {
                begin = j;
                chunk = 1;
            } else if r == a.len() + 1 - begin {
                break;
            } else {
                chunk *= 2;
            }
        }
        let &(cost, count) = unsafe { out.get_unchecked(a.len()) };
        if count > k {
            low = penalty + 1;
        } else {
            ret = cost.wrapping_sub(k as Cost * penalty);
            if count == k {
                return ret;
            }
            high = penalty - 1;
        }
    }
    ret
}

fn main() {
    let stdin = io::stdin();
    let mut lines = stdin.lock().lines();
    let k = lines.next().unwrap().unwrap().parse().unwrap();
    let a = lines
        .map(|s| s.unwrap().parse().unwrap())
        .collect::<Vec<_>>();
    let start = Instant::now();
    let cost = solve(k, &a);
    let time = start.elapsed();
    println!(
        "cost: {}\ntime: {}.{:09} sec",
        cost,
        time.as_secs(),
        time.subsec_nanos()
    );
}

इसे ऑनलाइन आज़माएं!

जंग , सबसे सुंदर स्कोर = 73

के साथ संकलित करें rustc -O। इनपुट फॉर्मेट Kपहली पंक्ति में है, इसके बाद Aएंट्री, प्रत्येक लाइन में एक प्रविष्टि, सभी स्टड पर।

use std::io::{self, BufRead};
use std::iter::once;
use std::num::Wrapping;
use std::time::Instant;
use std::u64;

type Cost = u64;
const INF: Cost = u64::MAX;

fn smawk<Col: Clone, Key: Ord, F: Clone + Fn(usize, &Col) -> Key>(
    n: usize,
    shift: u32,
    cols: &[Col],
    f: F,
) -> Vec<usize> {
    if n == 0 {
        Vec::new()
    } else if cols.len() > n {
        let mut s = Vec::with_capacity(n);
        let mut sk = Vec::with_capacity(n);
        for (jk, j) in cols.iter().enumerate() {
            while match s.last() {
                Some(l) => f(!(!(s.len() - 1) << shift), j) <= f(!(!(s.len() - 1) << shift), l),
                None => false,
            } {
                s.pop();
                sk.pop();
            }
            if s.len() < n {
                s.push(j.clone());
                sk.push(jk);
            }
        }
        smawk1(
            n,
            shift,
            cols,
            f.clone(),
            smawk(n / 2, shift + 1, &s, f)
                .into_iter()
                .map(|h| unsafe { *sk.get_unchecked(h) }),
        )
    } else {
        smawk1(
            n,
            shift,
            cols,
            f.clone(),
            smawk(n / 2, shift + 1, &cols, f).into_iter(),
        )
    }
}

fn smawk1<Col: Clone, Key: Ord, F: Clone + Fn(usize, &Col) -> Key, Iter: Iterator<Item = usize>>(
    n: usize,
    shift: u32,
    cols: &[Col],
    f: F,
    iter: Iter,
) -> Vec<usize> {
    let mut out = Vec::with_capacity(n);
    let mut range = 0..0;
    for (i, k) in iter.enumerate() {
        range.end = k + 1;
        out.push(
            range
                .clone()
                .zip(unsafe { cols.get_unchecked(range.clone()) })
                .min_by_key(|&(_, col)| f(!(!(2 * i) << shift), col))
                .unwrap()
                .0,
        );
        out.push(k);
        range.start = k;
    }
    if n % 2 == 1 {
        range.end = cols.len();
        out.push(
            range
                .clone()
                .zip(unsafe { cols.get_unchecked(range.clone()) })
                .min_by_key(|&(_, col)| f(!(!(n - 1) << shift), col))
                .unwrap()
                .0,
        );
    }
    out
}

fn solve(k: usize, a: &[Cost]) -> Cost {
    let mut cost = vec![INF; a.len() + 1 - k];
    let sa = once(Wrapping(0))
        .chain(a.iter().scan(Wrapping(0), |s, &x| {
            *s += Wrapping(x);
            Some(*s)
        }))
        .collect::<Vec<_>>();
    cost[0] = 0;
    let cols = (0..a.len() + 1 - k).collect::<Vec<_>>();
    for m in 0..k {
        cost = {
            let f = |i: usize, &j: &usize| {
                if i + 1 >= j {
                    let h = (i + 1 - j) / 2;
                    unsafe {
                        cost.get_unchecked(j).saturating_add(
                            (sa.get_unchecked(i + m + 1) - sa.get_unchecked(i + m + 1 - h)
                                - sa.get_unchecked(j + m + h)
                                + sa.get_unchecked(j + m))
                                .0,
                        )
                    }
                } else {
                    INF
                }
            };
            smawk(a.len() + 1 - k, 0, &cols, &f)
                .into_iter()
                .enumerate()
                .map(|(i, j)| f(i, &j))
                .collect()
        };
    }
    cost[a.len() - k]
}

fn main() {
    let stdin = io::stdin();
    let mut lines = stdin.lock().lines();
    let k = lines.next().unwrap().unwrap().parse().unwrap();
    let a = lines
        .map(|s| s.unwrap().parse().unwrap())
        .collect::<Vec<_>>();
    let start = Instant::now();
    let cost = solve(k, &a);
    let time = start.elapsed();
    println!(
        "cost: {}\ntime: {}.{:09} sec",
        cost,
        time.as_secs(),
        time.subsec_nanos()
    );
}

इसे ऑनलाइन आज़माएं!


आपको एक सुंदर स्कोर मिला है 61, लेकिन इसकी वजह यह है कि अतिप्रवाह u32। शायद आप 64-बिट पूर्णांक प्रकार में बदल सकते हैं?
कोलेरा सु

@ColeraSu अगर मैं अभी बदलूं तो क्या यह बेहतर type Cost = u32है type Cost = u64?
एंडर्स कासोर्ग

1
वाह, मैंने कभी SMAWK एल्गोरिथ्म के बारे में नहीं सोचा था। अच्छा काम है, आपको मिल गया 73
कोलेरा सु

2
@ng आपके पास जंग के खिलाफ क्या है? :-(
एंडर्स कासोर्ग

1
पहला इनाम जीतने के लिए बधाई!
Οवस

5

सी, स्कोर = 56

की सामग्री a.c:

typedef void V;typedef char C;typedef long L;typedef unsigned long U;
#define R return
#define W while
#define S static
#include<sys/syscall.h>
#define h1(f,x    )({L r;asm volatile("syscall":"=a"(r):"0"(SYS_##f),"D"(x)              :"cc","rcx","r11","memory");r;})
#define h3(f,x,y,z)({L r;asm volatile("syscall":"=a"(r):"0"(SYS_##f),"D"(x),"S"(y),"d"(z):"cc","rcx","r11","memory");r;})
#define read(a...) h3(read ,a)
#define write(a...)h3(write,a)
#define exit(a...) h1(exit ,a)
S V P(U x){C s[32],*p=s+32;*--p='\n';do{*--p='0'+x%10;x/=10;}W(x);write(1,p,s+32-p);}
S V mc(V*x,V*y,L n){C*p=x,*q=y;for(L i=0;i<n;i++)p[i]=q[i];}
#define min(x,y)({typeof(x)_x=(x),_y=(y);_x+(_y-_x)*(_y<_x);})
#define t(x,i,j)x[(i)*(n+n-(i)+1)/2+(j)] //triangle indexing
#define x(i,j)t(x,i,j)
#define y(i,j)t(y,i,j)
#define z(i,j)t(z,i,j)
#define N 4096 //max
L n;U ka[N+1],c[N],x[N*(N+1)/2],y[N*(N+1)/2],z[N*(N+1)/2];
V _start(){
 C s[1<<20];L r=0;U v=0;
 W(0<(r=read(0,s,sizeof(s))))for(L i=0;i<r;i++)if('0'<=s[i]&&s[i]<='9'){v=s[i]-'0'+10*v;}else{ka[n++]=v;v=0;}
 n--;U k=*ka,*a=ka+1;
 for(L i=n-1;i>=0;i--)for(L j=i-1;j>=0;j--)x(j,i)=x(j+1,i)-a[j]+a[i];
 for(L i=0;i<n;i++)for(L j=i+1;j<n;j++)y(i,j)=y(i,j-1)+a[j]-a[i];
 for(L i=n-1;i>=0;i--)for(L j=i+1;j<n;j++){
  U v=~0ul,*p=&x(i,i),*q=&y(i,j);for(L l=i;l<j;l++){v=min(v,*p+++*q);q+=n-l;} //min(v,x(i,l)+y(l,j));
  z(i,j)=v;}
 mc(c,z,8*n);
 for(L m=1;m<k;m++)for(L j=n-1;j>=m;j--){
  U v=~0ul,*p=&z(j,j);for(L i=j-1;i>=m-1;i--){v=min(v,c[i]+*p);p-=n-i;} //min(v,c[i]+z(i+1,j))
  c[j]=v;}
 P(c[n-1]);exit(0);}

उपर्युक्त संकलन और परीक्षण करने के लिए शेल स्क्रिप्ट:

#!/bin/bash -e
clang -O3 -nostdlib -ffreestanding -fno-unwind-tables -fno-unroll-loops -fomit-frame-pointer -oa a.c
strip -R.comment -R'.note*' a;stat -c'size:%s' a
t(){ r="$(echo "$1"|./a)";if [ "$r" != "$2" ];then echo "in:$1, expected:$2, actual:$r";fi;} #func tests
t '1 0 2 4 6 8' 12
t '3 0 1 10 11 20 21 22 30 32' 23
t '5 0 1 3 6 8 11 14' 3
t '6 0 1 3 6 8 14 15 18 29 30 38 41 45 46 49 58 66 72 83 84' 49
t '2 0 7 9' 2
for n in 1176 1351 1552 1782 2048;do #perf test
 echo "n:$n";a=0 inp="$((2*n/3))" RANDOM=1;for i in `seq $n`;do inp="$inp $a";a=$((a+=RANDOM%1000));done
 ulimit -t10 -v1048576;time ./a<<<"$inp"
done

n = 776 में 6.2s, n = 891 में 12s लगते हैं

n = 1176 5.9 लेता है, n = 1351 10 से अधिक लेता है

n = 1351 8.7 लेता है, n = 1552 मेरे पर 10s (k = 2 * n / 3 के साथ) से अधिक लेता है Intel(R) Core(TM) i3-2375M CPU @ 1.50GHz


2
मुझे लगता है कि यह कोड-गोल्फ नहीं है?
user202729

- @ user202729 यह कैसे मैं सामान्य रूप से लिखने सी कोड है incunabulum शैली।
ngn

@ मुझे लगता है कि तब भी आप आमतौर पर किसी भी तरह के वाक्य रचना हाइलाइटिंग का उपयोग नहीं करते हैं?
जोनाथन फ्रेच

@JonathanFrech मैं, वास्तव में। मैंने अपना कस्टमाइज़ कर लिया है syntax/c.vim
ngn

2
@cole यह केवल नियमित C है, केवल सघन है। यदि आप भाषा से परिचित हैं, तो आपको इसे बहुत कठिनाई के बिना पढ़ने में सक्षम होना चाहिए, हालांकि कई बार धीमी गति से, क्योंकि यहां एक पंक्ति में अधिकांश सी प्रोग्रामर की जानकारी होती है जो 5-10 लाइनों (क्या बेकार है) में फैल जाएगी। मैंने केवल मुश्किल बिट्स के लिए टिप्पणियां लिखीं।
ngn

3

सी ++, स्कोर = 53

उपाय मैंने टिप्पणी में कहा था। O(n²×k)। (अब मैंने इसे हटा दिया क्योंकि यह अब आवश्यक नहीं है) शायद इसे कम किया जा सकता है O(n×k)

इनपुट बहुत लचीला है, पहली पंक्ति पर, पहला नंबर है k, अन्य नंबर सरणी के आइटम हैं a, लेकिन अगर यह किसी भी करीबी कोष्ठक का सामना करता है तो यह इनपुट पढ़ना बंद कर देता है। इसलिए इनपुट K = 1, A = [0, 2, 4, 6, 8] : 12को स्वीकार किया जाता है।

// /codegolf/149029/build-an-electrical-grid

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <climits>

bool read(std::istream& str, int& x) {

    char ch;

    do {
        if (str >> x) return true;
        if (str.eof()) return false;
        str.clear(); // otherwise it's probably int parse error
    } while (str >> ch && ch != ']' && ch != ')' && ch != '}');
    // ignore 1 character, but treat any close parentheses as end of input

    // cannot read anything now
    return false;
}

int main() {
    int k; std::vector<int> a;

    //{ Read input
    std::string st; std::getline(std::cin, st);
    std::stringstream sst (st);

    read(sst, k);

    int x;
    while (read(sst, x)) a.push_back(x);
    //}

    std::vector<std::vector<int>> dp (a.size(), std::vector<int>(k));
    // dp[n][k] = min distance you can get for cities [n..a.size()-1]
    // and [k+1] power plants, and city [n] has a power plant.

    // sum_array[x] = sum of coordinates of cities [x..a.size()-1]
    std::vector<int> sum_array (a.size()+1);
    sum_array.back() = 0;
    for (int n = a.size(); n --> 0;)
        sum_array[n] = sum_array[n+1] + a[n];

    for (int n = a.size(); n --> 0;) {
        for (int k1 = k; k1 --> 0;) {
            if (k1 == 0) {
                int nWire = a.size() - 1 - n;
                dp[n][k1] = sum_array[n+1] - nWire * a[n];
            } else {
            // unindent because my screen width is limited

dp[n][k1] = INT_MAX / 2; // avoid stupid overflow error (in case of -ftrapv)

// let [n1] be the next position for a power plant
int first_connect_right = n; // < lengthy variable name kills screen width
// ^ lengthy comment kills screen width

for (int n1 = n + 1; n1 < (int)a.size(); ++n1) {

    while (a[first_connect_right]-a[n] < a[n1]-a[first_connect_right]) ++first_connect_right;

    int nRightWire = n1 - first_connect_right, nLeftWire = first_connect_right - 1 - n;
    dp[n][k1] = std::min(dp[n][k1],
        a[n1]*nRightWire-(sum_array[first_connect_right]-sum_array[n1]) +
        (sum_array[n+1]-sum_array[first_connect_right])-a[n]*nLeftWire +
        dp[n1][k1-1]
    );

}

            }

        }
    }

    int ans = INT_MAX;
    for (int n = a.size()+1-k; n --> 0;) {
        ans = std::min(ans, dp[n].back() + a[n]*n-sum_array[0]+sum_array[n]);
    }

    std::cout << ans << '\n';

    return 0;
}

इसे ऑनलाइन आज़माएं!

यादृच्छिक परीक्षण के मामले उत्पन्न करें। (इनपुट Nऔर वैकल्पिक रूप से शहर की सीमा, 1000×Nडिफ़ॉल्ट रूप से)


यदि ऐसा होता है कि कुछ बड़े परीक्षण मामले को हल करने में सक्षम होने के लिए, मैं आवश्यक intएस को बदल दूंगा int64_t
1520

dp [runned_n, runned_k] = min {dp [runned_n-x, runned_k] + f [x, n]}, इसलिए डायरेक्ट डायनेमिक प्रोग्रामिंग O (n ^ 2 * k) है। शायद जटिलता को कम करने के लिए पूरी तरह से बदलाव की आवश्यकता है?
l4m2

@ l4m2 एल्गोरिथ्म को खराब मत करो! (ठीक है, इनाम समाप्त नहीं हुआ है)
user202729

क्षमा करें, लेकिन मुझे नहीं पता कि आपका "खराब" मतलब "फेंक" या "चोरी" या दोनों है। दोनों अर्थ पा सकते हैं। मैं इस शब्द को काफी नहीं जानता। (मैंने यह भी सोचा है कि बाउंटी का मतलब बाध्य है)
l4m2

2
यादृच्छिक परीक्षण जनरेटर प्रश्न निर्दिष्ट करता है जैसे ए [0] = 0 लागू नहीं करता है।
एंडर्स कासोर्ग

2

सी #, स्कोर = 23

मुझे यकीन है कि यह इस चुनौती को जीतने नहीं जा रहा है, मैं सिर्फ अन्य लोगों को अपने एल्गोरिदम पोस्ट करने और मेरा सुधार करने के लिए प्रोत्साहित करने के लिए एक पहला (और बहुत ही मूल) उत्तर पोस्ट करना चाहता था। इस कोड को कंसोल प्रोजेक्ट के रूप में संकलित किया जाना चाहिए जो NuGet से कॉम्बिनेटरिक्स पैकेज का उपयोग करता है । मुख्य विधि में Buildप्रस्तावित मामलों का परीक्षण करने के लिए विधि में कुछ कॉल शामिल हैं।

using Combinatorics.Collections;
using System;

namespace ElectricalGrid
{
    class Program
    {
        static void Main(string[] args)
        {
            if (Build(1, new long[] { 0, 2, 4, 6, 8 }) == 12)
                Console.WriteLine("OK");
            else
                Console.WriteLine("ERROR");
            if (Build(3, new long[] { 0, 1, 10, 11, 20, 21, 22, 30, 32 }) == 23)
                Console.WriteLine("OK");
            else
                Console.WriteLine("ERROR");
            if (Build(5, new long[] { 0, 1, 3, 6, 8, 11, 14 }) == 3)
                Console.WriteLine("OK");
            else
                Console.WriteLine("ERROR");
            if (Build(6, new long[] { 0, 1, 3, 6, 8, 14, 15, 18, 29, 30, 38, 41, 45, 46, 49, 58, 66, 72, 83, 84 }) == 49)
                Console.WriteLine("OK");
            else
                Console.WriteLine("ERROR");

            Console.ReadKey();
        }

        static long Build(int k, long[] a)
        {
            var combs = new Combinations<long>(a, k);
            var totalDist = long.MaxValue;
            foreach (var c in combs)
            {
                long tempDist = 0;
                foreach (var i in a)
                {
                    var dist = long.MaxValue;
                    foreach (var e in c)
                    {
                        var t = Math.Abs(i - e);
                        if (t < dist) dist = t;
                    }
                    tempDist += dist;
                }
                if (tempDist < totalDist) totalDist = tempDist;
            }
            return totalDist;
        }
    }
}

वास्तव में सरल व्याख्या: cसे kतत्वों के प्रत्येक संयोजन के लिए, निकटतम तत्व के aप्रत्येक तत्व से दूरी की राशि की गणना करें और कम से कम कुल दूरी के साथ संयोजन को वापस करें।ac

Buildविधि का एक-लाइनर संस्करण (शायद मूल, विस्तारित संस्करण की तुलना में धीमा; यह एक संदर्भ जोड़ने की जरूरत है System.Linq):

static long Build(int k, long[] a)
{
    return new Combinations<long>(a, k).Min(c => a.Sum(i => c.Min(e => Math.Abs(i - e))));
}

2

सी ++, स्कोर = 48

#include <stdio.h>
#include <queue>
#include <algorithm>
typedef long long ull;
typedef unsigned int uint;
uint A[1<<20];
ull S[1<<20];

double ky = 1;
struct point {
    ull dist;
    int n;
    inline point() {}
    inline point(ull dist, int n): dist(dist), n(n) {}
    inline double res() const{
        return dist + n * ky;
    }
    inline int operator<(const point& other) const {
        return res() < other.res();
    }
} V[1<<20];
inline ull f(int L, int R) {
    int m = L+R+1 >> 1;
    return (S[R]-S[m]) - A[m]*(R-m) +
           A[m]*(m-L) - (S[m]-S[L]);
}
int main() {
    int N, K, i, j, p;
    scanf ("%d%d", &N, &K);
    ull s = 0;
    for (i=1; i<=N; i++) {
        scanf ("%u", A+i);
        S[i] = s += A[i];
    }
    double kyL = 0, kyH = 1e99;
    point cL, cR;
    for (int step=0; step++<50; ky = std::min(ky*2, (kyL+kyH)*.5)) {
        for (i=1; i<=N; i++) {
            point tmp(f(0,i), 1);
            for (j=1; j<i; j++) {
            //printf("ky=%f [%d]=%d %I64d %f\n", ky, i, tmp.n, tmp.dist, tmp.res());
                point cmp = V[j];
                cmp.dist += f(j, i);
                cmp.n ++;
                if (cmp<tmp) tmp=cmp;
            }
            //printf("ky=%f [%d]=%d %I64d %f\n", ky, i, tmp.n, tmp.dist, tmp.res());
            V[i] = tmp;
        }
        if (V[N].n == K) {
_:          return! printf("%I64d", V[N].dist);
        }
        if (V[N].n > K) {
            kyL = ky;
            cL = V[N];
        } else {
            kyH = ky;
            cR = V[N];
        }
        //printf("ky=%f %d %I64d %f\n", ky, V[N].n, V[N].dist, V[N].res());
        //getch();
    }
    V[N].dist = (double)cL.dist / (cR.n-cL.n) * (K-cL.n) +
                (double)cR.dist / (cL.n-cR.n) * (K-cR.n) + .5;
    printf("%I64d", V[N].dist);
}

उपयोग इनपुट: एनकेए [1] ए [२] ... ए [एन]


2
यदि आप step70 की सीमा बढ़ाते हैं , तो आपका सबसे बड़ा स्कोर 60 है।
कोलेरा सु


2

जावास्क्रिप्ट (ES6) (Node.js) , स्कोर = 10

नया एल्गोरिथम, समझाएगा कि क्या यह वास्तव में इस समय काम करता है।

const {performance} = require('perf_hooks');

class Connection{
    constructor(left,index,length,right){
        if(typeof right === 'undefined'){
            this._distance = 0;
        } else {
            this._distance = typeof left === 'undefined' ? 0 :
                    Math.abs(right - left);
        }
        var half = Math.floor(length/2);
        if(length % 2 < 1){
            this._magnitude = half - Math.abs(index - half + 1);
        } else {
            var temp = index - half;
            this._magnitude = half - Math.abs(temp >= 0 ?temp:temp + 1);
        }
        this._value = this.distance * this.magnitude;
    }

    get distance(){return this._distance;};
    get magnitude(){return this._magnitude;};
    set magnitude(value){
        this._magnitude = value;
        this._value = this.distance * this.magnitude;
    };
    valueOf(){return this._value};
}

class Group{
	constructor(...connections){
        this._connections = connections;
		
		this._max = Math.max(...connections); //uses the ValueOf to get the highest Distance to the Left
	}
	get connections(){return this._connections;};
	get max(){return this._max;};
    cutLeft(index){

            for(let i=1,j=index-1;;i++){
                
                if(typeof this.connections[j] === 'undefined' || this.connections[j].magnitude <= i){
                    break;
                }
                this.connections[j].magnitude = i;
                j--;
            }

    }

    cutRight(index){

            for(let i=0,j=index;;i++){
                
                if(typeof this.connections[j] === 'undefined' || this.connections[j].magnitude <= i){
                    break;
                }
                this.connections[j].magnitude = i;
                j++;
            }

    }

    static of(...connections){
        return new Group(...connections.map((c,i)=>new Connection(c.distance,i,connections.length)));
    }

	split(){
        var index = this.connections.findIndex(c=>c.valueOf() == this.max);
        if(index < 0){
            return;
        }
        var length = this.connections.length;
        var magnitude = this.connections[index].magnitude;

        this.cutLeft(index);
        this.cutRight(index);
        this._max = Math.max(...this.connections);
	}

    center(){
        if(typeof this._center === 'undefined'){
            this._center = this.connections.reduce((a,b)=>a==0?b.valueOf():a.valueOf()+b.valueOf(),0);
        }
        return this._center;
    }

    valueOf(){return this._max;};
    toString(){
        var index = this.connections.findIndex(c=>c.valueOf() == this.max);
        var value = this.connections[index].magnitude;
        var ret = '';
        for(let i = 0;i<value;i++){
            ret += this.connections.map(c=>{return (i<c.magnitude)?c.distance:' ';}).reduce((a,b)=>a==''?b:a+'-'+b,'') + '\n';
        }
        return ret;
    };
}

function crunch(plants, cities){
	var found = [];
    var size = cities.length;
    cities = cities.map((city,i,arr)=> new Connection(city,i,size,arr[i+1])).slice(0,cities.length-1);
    var group = new Group(...cities);
    for(;plants>1;plants--){
    group.split();
    }
    console.log(`Wire Length Needed: ${group.center()}`);
}

function biggestGroup(groups){
	return groups.find(g => g[g.length-1].orig - g[0].orig);
}

function* range (start, end, limit) {
    while (start < end || typeof limit !== 'undefined' && limit-- > 0) {
        yield start
        start += 1 + Math.floor(Math.random()*100);
    }
}

function* cities (score){
	let n = Math.floor(Math.pow(2,score/5));
	var start = 0;
	while (n-- > 0 && start <= (1000 * n)) {
		yield start;
        start += 1 + Math.floor(Math.random()*100);
    }
}


if(typeof process.argv[3] === 'undefined'){
    crunch(1,[0, 2, 4, 6, 8]);
    console.log("Correct Answer: 12");
    crunch(3,[0, 1, 10, 11, 20, 21, 22, 30, 32]);
    console.log("Correct Answer: 23");
    crunch(5,[0, 1, 3, 6, 8, 11, 14]);
    console.log("Correct Answer: 3");
    crunch(6,[0, 1, 3, 6, 8, 14, 15, 18, 29, 30, 38, 41, 45, 46, 49, 58, 66, 72, 83, 84]);
    console.log("Correct Answer: 49");
    crunch(2, [0, 21, 31, 45, 49, 54]);
    console.log("Correct Answer: 40");
    crunch(2, [0, 4, 7, 9, 10]);
    console.log("Correct Answer: 7");
    crunch(2, [0, 1, 3, 4, 9]);
    console.log("Correct Answer: 6");
    
    var max = 0;
    var min = Number.POSITIVE_INFINITY;
    var avg = [];
    
    var score = typeof process.argv[2] === 'undefined' ? 60 : process.argv[2];

    for(j = 0; j<10; j++){
        var arr = []; for(let i of cities(score)) arr.push(i);
        var plants = Math.floor(1 + Math.random() * arr.length);
        console.log(`Running: Test:${j} Plants: ${plants}, Cities ${arr.length}, Score: ${score}`);
        // console.log(`City Array: [${arr}]`);
        var t0 = performance.now();
        crunch(plants,arr);
        var t1 = performance.now();
        time = (t1-t0)/1000;
        console.log(`Time Taken = ${time} seconds`);
        avg.push(time);
        max = Math.max(time,max);
        min = Math.min(time,min);
    }
    console.log(`Bench: ${avg.reduce((a,b)=>a+b,0)/avg.length} Max: ${max} Min: ${min} Total: ${avg.reduce((a,b)=>a+b,0)}`);
} else {
    var plants = process.argv[2];
    var arr = process.argv.slice(3);
    console.log(`Running: Plants: ${plants}, Cities ${arr.length}`);
    var t0 = performance.now();
    crunch(plants,arr);
    var t1 = performance.now();
    time = (t1-t0)/1000;
    console.log(`Time Taken = ${time} seconds`);
}

इसे ऑनलाइन आज़माएं!

दूसरी तरह से भी चलाएं।

जावास्क्रिप्ट (ES6) (Node.js) , सबसे सुंदर स्कोर = 12

एल्गोरिथ्म की रूपरेखा:

कार्यक्रम पहले डेटा को सिटी क्लास में मैप करता है, जो कुछ डेटा बिंदुओं को मैप करता है:

  • शहर - शहर की पूर्ण दूरी
  • बाईं ओर - निकटतम शहर की दूरी बाईं ओर
  • दाईं ओर - निकटतम शहर की दूरी दाईं ओर
  • सूचकांक - (पदावनत) मूल शहर सरणी में सूचकांक

फिर सरणी को समूह वर्ग में फेंक दिया जाता है, जिसमें निम्नलिखित हैं:

  • शहर - शहर सरणी
  • दूर - समूह फैले दूरी
  • अधिकतम - समूह में सबसे बड़ा बाएं कनेक्शन
  • विभाजित करें()
    • समूह में केंद्र शहर से जुड़े सबसे बड़े कनेक्शन के साथ उप समूहों को विभाजित करने वाला एक सरणी देता है
    • अगर वहाँ 2 केंद्र नोड्स हैं (एक भी लंबाई समूह) यह उन 3 कनेक्शनों में से चुनता है
    • (* नोट *: यह दो शहरों से कम वाले किसी भी समूह को छोड़ देगा)
  • केंद्र ()
    • समूह के लिए सबसे अच्छा तार मान लौटाता है
    • इस कदम के लिए छोड़ दिया प्रत्येक शहर पर पुनरावृत्ति को छोड़ने के लिए एक समाधान पर काम कर रहा है
    • अब 50% कम मैपिंग के साथ

अब एल्गोरिथ्म समूहों को विभाजित करने के लिए आगे बढ़ता है, जब तक कि इसमें 2 या अधिक बिजली संयंत्र नहीं होते हैं।

अंत में यह समूहों को केंद्रों में मैप करता है, और उन सभी को रकम देता है।

कैसे चलाएं:

Node.js (v9.2.0 का उपयोग सृजन के लिए किया गया था) का उपयोग करके चलाएं

स्कोर 70 के लिए उत्पन्न परीक्षण मामलों का उपयोग करके कार्यक्रम चलाना:

node program.js 70

1 पावर प्लांट और शहरों का उपयोग करके कार्यक्रम चलाना [0,3,5]:

node program.js 1 0 3 5

कोड:

const {performance} = require('perf_hooks');

class City{
	constructor(city, left, right, i){
		this._city = city;
		this._index = i;
		this._left = typeof left === 'undefined' ? 0 : city - left;
		this._right = typeof right === 'undefined' ? 0 : right - city;
	}

	get city(){return this._city;};
	get index(){return this._index;};
	get left(){return this._left;};
    get right(){return this._right;};
    set left(left){this._left = left};
    set right(right){this._right = right};

	valueOf(){return this._left;};
}

class Group{
	constructor(...cities){
        this._cities = cities;
        // console.log(cities.map(a=>a.city).reduce((a,b)=>a===''?a+(b<10?' '+b:b):a+'-'+(b<10?' '+b:b),""));
        // console.log(cities.map(a=>a.left).reduce((a,b)=>a===''?a+(b<10?' '+b:b):a+'-'+(b<10?' '+b:b),""));
        // console.log(cities.map(a=>a.right).reduce((a,b)=>a===''?a+(b<10?' '+b:b):a+'-'+(b<10?' '+b:b),""));
        // console.log("+==+==+==+==+==+==+==+==+==+==+==+==")
		this._dist = cities[cities.length-1].city - cities[0].city;
		this._max = Math.max(...cities); //uses the ValueOf to get the highest Distance to the Left
	}

	get dist(){return this._dist;};
	get cities(){return this._cities;};
	get max(){return this._max;};

	split(){
        //var index = this.cities.findIndex(city=>city.left == this.max);
        //this.cities[index].left = 0;
        // console.log(`Slicing-${this.max}-${index}------`)
        var centerIndex = this.cities.length / 2;
        var splitIndex = Math.floor(centerIndex);
        if(centerIndex%1 > 0){
            var center = this.cities[splitIndex];
            if(center.right > center.left){

                splitIndex++;
            }
        } else {
            var right = this.cities[splitIndex];
            var left = this.cities[splitIndex-1];
            if(left.left > Math.max(right.right,right.left)){
               
                splitIndex--;
            } else if(right.right > Math.max(left.left,left.right)){
                
                splitIndex++;
            }
        }
        // console.log(splitIndex);
        this.cities[splitIndex].left = 0;
        this.cities[splitIndex-1].right = 0;
        var leftCities = [...this.cities.slice(0,splitIndex)];
        var rightCities = [...this.cities.slice(splitIndex)];

        // var center = this.cities[]

        if(leftCities.length <= 1){
            if(rightCities.length <= 1){
                return [];
            }
            return [new Group(...rightCities)]
        }
        if(rightCities.length <= 1){
            return [new Group(...leftCities)];
        }
        return [new Group(...leftCities), new Group(...rightCities)];
	}

    center(){
        if(typeof this._center === 'undefined'){
            if(this.cities.length == 1){
                return [0];
            }
            if(this.cities.length == 2){
                return this.cities[1].left;
            }
            var index = Math.floor(this.cities.length/2);
            this._center = this.cities.reduce((a,b)=> {
                // console.log(`${a} + (${b.city} - ${city.city})`);
                return a + Math.abs(b.city - this.cities[index].city);
            },0);
            // console.log(this._center);
        }
        
        return this._center;
    }

	valueOf(){return this._max;};
}

function crunch(plants, cities){
	var found = [];
    var size = cities.length;
    cities = cities.map((city,i,arr)=> new City(city,arr[i-1],arr[i+1],i));
	var groups = [new Group(...cities)];

	// console.log(groups);
    for(;plants>1;plants--){
        var mapped = groups.map(g=>g.center()-g.max);
        var largest = Math.max(...groups);
        // console.log('Largest:',largest)
        // console.log(...mapped);
		var index = groups.findIndex((g,i)=> mapped[i] == g.center() - g.max && g.max == largest);
		// console.log(index);
        groups = index == 0 ? 
            [...groups[index].split(),...groups.slice(index+1)]:
            [...groups.slice(0,index),...groups[index].split(),...groups.slice(index+1)];
    }
    // console.log(`=Cities=${size}================`);
    // console.log(groups);
    size = groups.map(g=>g.cities.length).reduce((a,b)=>a+b,0);
    
    // console.log(`=Cities=${size}================`);
    var wires = groups.map(g=>g.center());
    
    // console.log(...wires);
    // console.log(`=Cities=${size}================`);
    console.log(`Wire Length Needed: ${wires.reduce((a,b)=>a + b,0)}`);
}

function biggestGroup(groups){
	return groups.find(g => g[g.length-1].orig - g[0].orig);
}

function* range (start, end, limit) {
    while (start < end || typeof limit !== 'undefined' && limit-- > 0) {
        yield start
        start += 1 + Math.floor(Math.random()*100);
    }
}

function* cities (score){
	let n = Math.floor(Math.pow(2,score/5));
	var start = 0;
	while (n-- > 0 && start <= (1000 * n)) {
		yield start;
        start += 1 + Math.floor(Math.random()*100);
    }
}

if(typeof process.argv[3] === 'undefined'){
    crunch(1,[0, 2, 4, 6, 8]);
    console.log("Correct Answer: 12");
    crunch(3,[0, 1, 10, 11, 20, 21, 22, 30, 32]);
    console.log("Correct Answer: 23");
    crunch(5,[0, 1, 3, 6, 8, 11, 14]);
    console.log("Correct Answer: 3");
    crunch(6,[0, 1, 3, 6, 8, 14, 15, 18, 29, 30, 38, 41, 45, 46, 49, 58, 66, 72, 83, 84]);
    console.log("Correct Answer: 49");
    crunch(2, [0, 21, 31, 45, 49, 54]);
    console.log("Correct Answer: 40");
    crunch(2, [0, 4, 7, 9, 10]);
    console.log("Correct Answer: 7");
    
    var max = 0;
    var min = Number.POSITIVE_INFINITY;
    var avg = [];
    
    var score = typeof process.argv[2] === 'undefined' ? 60 : process.argv[2];

    for(j = 0; j<10; j++){
        var arr = []; for(let i of cities(score)) arr.push(i);
        var plants = Math.floor(1 + Math.random() * arr.length);
        console.log(`Running: Test:${j} Plants: ${plants}, Cities ${arr.length}, Score: ${score}`);
        var t0 = performance.now();
        crunch(plants,arr);
        var t1 = performance.now();
        time = (t1-t0)/1000;
        console.log(`Time Taken = ${time} seconds`);
        avg.push(time);
        max = Math.max(time,max);
        min = Math.min(time,min);
    }
    console.log(`Bench: ${avg.reduce((a,b)=>a+b,0)/avg.length} Max: ${max} Min: ${min} Total: ${avg.reduce((a,b)=>a+b,0)}`);
} else {
    var plants = process.argv[2];
    var arr = process.argv.slice(3);
    console.log(`Running: Plants: ${plants}, Cities ${arr.length}`);
    var t0 = performance.now();
    crunch(plants,arr);
    var t1 = performance.now();
    time = (t1-t0)/1000;
    console.log(`Time Taken = ${time} seconds`);
}

इसे ऑनलाइन आज़माएं!

मैं अगले कुछ दिनों में टिप्पणी के बाहर कोड को साफ कर दूंगा क्योंकि मैं अभी भी इस पर काम कर रहा हूं, बस यह देखना चाहता था कि क्या यह सिर्फ छोटे मामलों से अधिक गुजर रहा था।


टेस्टकेस पर विचार करें K = 2, A = [0, 21, 31, 45, 49, 54]। सही उत्तर 40 है, लेकिन आपका प्रोग्राम 51 का आउटपुट देता है।
कोलेरा सु

और भी सरल K = 2, A = [0, 4, 7, 9, 10]:। सही: 7, आपका जवाब: 8.
कालरा सु

ठीक है अब यह काम करना चाहिए ... यह कम से कम सभी प्रदान किए गए मामलों के लिए काम करता है।
विल्सन जॉनसन Reta232

वास्तव में मैं एक और एल्गोरिथ्म भी प्राप्त कर सकता हूं जो बेहतर काम करता है। मैं सिद्धांत का परीक्षण करने और इसे थोड़ा पोस्ट करने जा रहा हूं।
विल्सन जॉनसन Reta232

फिर भी काम नहीं कर रहा ... K = 2, A = [0, 1, 3, 4, 9]। Correct: 6, आपका उत्तर: 7.
Colera Su

1

सी (गैर-प्रतिस्पर्धात्मक, सबसे सुंदर स्कोर = 76)

यह @ AndersKaseorg का दूसरा रस्ट सॉल्यूशन C पर अनुवाद करने का एक प्रयास है।

typedef void V;typedef char C;typedef long L;
#define R return
#define W while
#define S static
#include<sys/syscall.h>
#define exit(x)     ({L r;asm volatile("syscall":"=a"(r):"0"(SYS_exit ),"D"(x)              :"cc","rcx","r11","memory");r;})
#define read(x,y,z) ({L r;asm volatile("syscall":"=a"(r):"0"(SYS_read ),"D"(x),"S"(y),"d"(z):"cc","rcx","r11","memory");r;})
#define write(x,y,z)({L r;asm volatile("syscall":"=a"(r):"0"(SYS_write),"D"(x),"S"(y),"d"(z):"cc","rcx","r11","memory");r;})
S V P(L x){C s[32],*p=s+32;*--p='\n';do{*--p='0'+x%10;x/=10;}W(x);write(1,p,s+32-p);}
#define N 0x100000 //max
#define INF (-1ul>>1)
S L cost[N],nk1,*am; //nk1:n-k+1, am:input's partial sums offset with the current "m" in _start()
S L f(L i,L j){if(i+1>=j&&cost[j]!=INF){L h=(i-j+1)>>1;R cost[j]+am[i+1]-am[j+h]-am[i-h+1]+am[j];}else{R INF;}}
S V smawk(L sh,L*c,L nc,L*r){ //sh:shift,c:cols,r:result
 L n=nk1>>sh;if(!n)R;
 L m=n>>1,u[m];
 if(n<nc){
  L ns=0,s[nc],sk[nc],*skp=sk;
  for(L jk=0;jk<nc;jk++){
   L j=c[jk];W(ns>0&&f(~(~(ns-1)<<sh),j)<=f(~(~(ns-1)<<sh),s[ns-1])){--ns;--skp;}
   if(ns<n){s[ns++]=j;*skp++=jk;}
  }
  smawk(sh+1,s,ns,u);for(L i=0;i<m;i++)u[i]=sk[u[i]];
 }else{
  smawk(sh+1,c,nc,u);
 }
 L l=0,ish=(1<<sh)-1,dsh=1<<(sh+1);
 for(L i=0;i<m;i++){
  L k=u[i],bj=l,bc=f(ish,c[l]);
  for(L j=l+1;j<=k;j++){L h=f(ish,c[j]);if(h<bc){bc=h;bj=j;}}
  *r++=bj;*r++=k;l=k;ish+=dsh;
 }
 if(n&1){
  L nsh=~(~(n-1)<<sh),bj=l,bc=f(nsh,c[l]);
  for(L j=l+1;j<nc;j++){L h=f(nsh,c[j]);if(h<bc){bc=h;bj=j;}}
  *r=bj;
 }
}
S L inp(L*a){
 L n=-1,l,v=0;C b[1<<20];
 W(0<(l=read(0,b,sizeof(b))))for(L i=0;i<l;i++)if('0'<=b[i]&&b[i]<='9'){v=b[i]-'0'+10*v;}else{a[++n]=v;v=0;}
 R n;
}
V _start(){
 S L a[N];L n=inp(a),k=*a,s=0;for(L i=0;i<n;i++){a[i]=s;s+=a[i+1];}a[n]=s;
 *cost=0;for(L i=1,l=n+1-k;i<l;i++)cost[i]=INF;
 S L c[N];L nc=n+1-k;for(L i=0;i<nc;i++)c[i]=i;
 S L r[N];nk1=n-k+1;for(L m=0;m<k;m++){am=a+m;smawk(0,c,nc,r);for(L i=n-k;i>=0;i--)cost[i]=f(i,r[i]);}
 P(cost[n-k]);exit(0);
}

संकलन:

#!/bin/bash -e
clang -O3 -nostdlib -ffreestanding -fno-unwind-tables -fno-unroll-loops -fomit-frame-pointer -oa a.c
strip -R.comment -R'.note*' a

1

क्लीन , स्कोर = 65

module main
import StdEnv, System.IO

parseArgs :: *World -> ((Int, {#Int}), *World)
parseArgs world
    # (args, world)
        = nextArgs [] world
    # args
        = reverse args
    # (k, a)
        = (hd args, tl args)
    = ((toInt k, {toInt n \\ n <- a}), world)
where
    nextArgs :: [String] *World -> ([String], *World)
    nextArgs args world
        # (arg, world)
            = evalIO getLine world
        | arg == ""
            = (args, world)
        = nextArgs [arg:args] world

minimalWeight :: Int !{#Int} -> Int
minimalWeight k a
    # count
        = size a
    # touches
        = createArray ((count - k + 3) / 2 * k) 0
    = treeWalk k count a [(0, 0, 0, 0)] touches
where
    treeWalk :: Int !Int {#Int} ![(!Int, !Int, Int, Int)] *{Int} -> Int
    treeWalk k verticies a [(weight, vertex, degree, requires) : nodes] touches
        | vertex >= verticies
            = weight
        | requires >= k
            = treeWalk k verticies a nodes touches
        # index
            = degree * k + requires
        | (select touches index) > vertex
            = treeWalk k verticies a nodes touches
        # (next, pivot)
            = (vertex + 1 + degree, verticies + requires)
        # (nodes, touches)
            = (orderedPrepend (weight, next, 0, requires + 1) nodes, update touches index (vertex + 1))
        | pivot >= k + next
            # (weight, vertex)
                = (weight + (select a next) - (select a vertex), vertex + 1)
            # nodes
                = orderedPrepend (weight, next + 1, 0, requires + 1) nodes
            | pivot == k + next
                = treeWalk k verticies a nodes touches
            # weight
                = weight + (select a (next + 1)) - (select a vertex)
            # nodes
                = orderedPrepend (weight, vertex, degree + 1, requires) nodes
            = treeWalk k verticies a nodes touches
        = treeWalk k verticies a nodes touches
    where
        orderedPrepend :: (!Int, Int, Int, Int) ![(!Int, Int, Int, Int)] -> [(Int, Int, Int, Int)]
        orderedPrepend a []
            = [a]
        orderedPrepend a [b : b_]
            # (x, _, _, _)
                = a
            # (y, _, _, _)
                = b
            | y > x
                = [a, b : b_]
            = [b : orderedPrepend a b_]

Start world
    # ((k, a), world)
        = parseArgs world
    = minimalWeight k a

संकलन:
clm -h 1024M -gci 32M -gcf 32 -s 32M -t -nci -ou -fusion -dynamics -IL Platform main

कमांड लाइन तर्क के रूप में K, और फिर प्रत्येक तत्व लेता Aहै।


@ColeraSu मैं पूछ सकता हूं कि स्कोर में निर्णायक कारक क्या था? सुधार / समय / स्मृति? मुझे उम्मीद है कि यह समय था।
Οवस

आप सही कह रहे हैं, यह समय था।
कोलेरा सु
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.