SPOJ i zadanie "Obżartuchy" - wynik nie zawsze jest poprawny

0

http://pl.spoj.com/problems/GLUTTON/
Zadanie mam praktycznie zrobione, oto mój kod:

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
    float pudelka, czasy[10000], N, M;
    int ile, j;

    cin>>ile;
for(int i=0; i<ile; i++)
{

    cin>>N>>M;
    j=0;
    pudelka=0;

    do
    {
        cin>>czasy[j];
        pudelka+=(24/(czasy[j]/3600))/M;
        j++;
    } while(j<N);

    cout<<ceil(pudelka)<<endl<<endl;
}

    return 0;
}

Jednak jest mały problem. Wpisuję wejścia zgodnie z tymi podanymi na stronie i wychodzi mi dobry wynik dla pierwszego testu, jednak dla drugiego już nie do końca. Na stronie wynik wynosi 2, u mnie pokazuje 3, gdyż bez "ceil" wychodzi niby 2.00452. Domyślam się, że może się tak dziać z powodu przybliżeń (w którymś działaniu jak patrzyłem na kartce był wynik okresowy po przecinku). Natknąłem się też na troszkę inny wzór obliczania ilości tych pudełek: N.push_back((((3600 / czas) * 24) + ciastka - 1) / ciastka); ale nie mam pojęcia, skąd się to bierze i jak można było wpaść na ten wzór :P. Tak więc mam 2 pytanka:

  1. Da się ten problem rozwiązać moim sposobem, wprowadzając jakieś lekkie modyfikacje czy jest on z góry skazany na porażkę ze względu na te przybliżenia lub przez coś innego, czego nie widzę?
  2. Jak ten drugi wzór został wyprowadzony? W ogóle go nie rozumiem.
0
  1. Na spoj wyjście samo się oddziela od wejścia, więc nie musisz magazynować wyników
  2. cin/cout są powolne, używaj scanf/printf lub przynajmniej http://www.cplusplus.com/reference/ios/ios_base/sync_with_stdio/
  3. Twój problem polega na tym:
#include <iostream>
using namespace std;

int main()
  {
   double sum=0;
   for(int i=0;i<10;++i) sum+=0.1;
   if(sum!=1) cout<<"UWAGA! 10 * 0.1 != 1"<<endl;
   return 0;
  }

http://ideone.com/GxMnp4 Czyli zbyt wcześnie dzielisz.
4. Na spoj'u przechodzi to:

#include <cstdio>
using namespace std;

int main()
  {
   unsigned T,N,M,X;
   unsigned long long sum;
   for(scanf("%u",&T);T--;printf("%llu\n",(sum+M-1)/M)) for(sum=0,scanf("%u%u",&N,&M);N--;sum+=24*60*60/X) scanf("%u",&X);
   return 0;
  }
1
#include <cstdio>
using namespace std;
 
int main()
  {
   unsigned T,N,M,X;
   unsigned long long sum;
   for(scanf("%u",&T);T--;printf("%llu\n",(sum+M-1)/M)) for(sum=0,scanf("%u%u",&N,&M);N--;sum+=24*60*60/X) scanf("%u",&X);
   return 0;
  }

Dragon, ile pijesz zanim zaczniesz pisać taki kod ? A poważnie, piszesz tak na codzień w kodzie który poprawia parę osób ?
Fakt, jestem pod wrażeniem ale zastanawiam się jak szybko przychodzi Ci takie rozwiązanie ? Bo jest na tyle 'skomplikowane' że trzeba trochę pomyśleć nad nim, żeby go zrozumieć a co dopiero samemu napisać, a kod powinien być przede wszystkim czytelny (?).

Bynajmniej nie krytykuje bo kod powinien być krótki jak tylko się da, bo można popełnić jak najmniej błąd tylko nie wiem czy aż w tę stronę.

0

SPOJ oraz różne fora traktuję jako taki trening skondensowanego pisania.
Po pierwsze - szybciej się pisze, po drugie - (jak już zauważyłeś) mniejsza szansa popełnienia błędu.
W poważnym projekcie ten kod mógłby wyglądać np tak:

#include <cstdio>
using namespace std;
 
int main()
  {
   unsigned T;
   scanf("%u",&T);
   while(T--)
     {
      unsigned N,M;
      scanf("%u%u",&N,&M);
      unsigned long long sum=0;
      while(N--)
        {
         unsigned X;
         scanf("%u",&X);
         sum+=24*60*60/X;
        }
      printf("%llu\n",(sum+M-1)/M);
     }
   return 0;
  }

oczywiście zmienne muszą mieć jakieś znaczenie, tu mają ponieważ w zadaniu są właśnie tak nazwane (oprócz X i sum).
Aczkolwiek w pewnych miejscach (tak zwany core) który mają prawo dotykać wyłacznie zaawansowane umysłowo programiści bez zahamowań piszę jednowierszowce.

1 użytkowników online, w tym zalogowanych: 0, gości: 1