Pagini recente » Cod sursa (job #1903533) | Cod sursa (job #671266) | Cod sursa (job #1208422) | Cod sursa (job #2796659) | Cod sursa (job #2750980)
#include <iostream>
#include <fstream>
#include <cstring>
#define NMAX 100
#define LMAX 100
#define TIMPMINIM 1
#define TIMPMAXIM 100
using namespace std;
ifstream fin ("lapte.in");
ofstream fout ("lapte.out");
int N, L;
int v[NMAX + 1][LMAX / TIMPMINIM * NMAX + 1];
int RASPUNS;
struct persoana{
int A, B;
}timp[NMAX + 1];
struct repartizare{
int A, B;
}cantitate[NMAX + 1][2 * LMAX - 2 + 1];
int valid(int TIMP){
//verific daca in acest timp, utilizand tactica optima, se pot bea L litri din fiecare lapte
memset(v, 0, sizeof(v));
int CAMAX = 2 * L - 2;
//initializez
for(int Ca = 0; Ca <= CAMAX; Ca++){
v[1][Ca] = max(0, TIMP - Ca * timp[1].A / timp[1].B) ;
if(v[1][Ca] != 0){
cantitate[1][Ca].A = Ca;
cantitate[1][Ca].B = TIMP - Ca * timp[1].A / timp[1].B;
}
}
for(int i = 2; i <= N; i++){
for(int Ca = 0; Ca <= CAMAX; Ca++){
for(int Z = 0; Z <= Ca && TIMP - Z * timp[i].A >= 0; Z++){ //Z = cantitatea pe care omul i o bea din laptele A
//v[i][Ca] = max(v[i][Ca], v[i - 1][Ca - Z] + (TIMP - Z * timp[i].A) / timp[i].B );
if(v[i - 1][Ca - Z] != 0){
int candidat = v[i - 1][Ca - Z] + (TIMP - Z * timp[i].A) / timp[i].B;
if(i >= 1){
//cout << "Ca = " << Ca << "\ni = " << i << "\nZ = " << Z << "\ncandidat = v[ " << i - 1 << " ][ " << Ca - Z << " ]("<<v[i - 1][Ca - Z]<<") + ( " << TIMP << " - " << Z * timp[i].A << " ) / " << timp[i].B << " = " << candidat << "\nv[ " << i << " ][ " << Ca << " ] = " << v[i][Ca] << "\n\n";
}
if( candidat > v[i][Ca] ){
v[i][Ca] = candidat;
cantitate[i][Ca].A = Z;
cantitate[i][Ca].B = (TIMP - Z * timp[i].A) / timp[i].B;
for(int j = 1; j <= i - 1; j++){
cantitate[j][Ca].A = cantitate[j][Ca - Z].A;
cantitate[j][Ca].B = cantitate[j][Ca - Z].B;
}
}
}
}
}
}
/*
for(int i = 1; i <= N; i++){
for(int j = 0; j <= CAMAX; j++){
cout << "v[ " << i << " ][ " << j << " ] = " << v[i][j] << "\n";
}
cout << "\n";
}
cout << "\n";
*/
int cntA = L;
while(cntA <= CAMAX && v[N][cntA] == 0){
cntA++;
}
if(cntA <= CAMAX){
if(v[N][cntA] >= L){
RASPUNS = cntA;
return 1;
}
else{
return 0;
}
}
else {
return 0;
}
}
/*
(TIMP - Z * timp[i].A)
ramas pentru a bea din laptele b
din care bea un litru in timp[i].B secunde
(TIMP - Z * timp[i].A) div timp[i].B litri apuca sa bea
pt v[i][Ca] stiu sigur ca am o submultime ce contine doar numere dintre [1, i] (nu neaparat pe toate)
iar fiecare submultime a baut cantitatea Ca de lapte A
pt fiecare din submultimi, le stiu pe acelea care au cantitatea B de lapte bauta maxim
TIMP = timpul MAXIM in care se poate ajunge la o configuratie buna
daca eu beau pt o persoana un timp tA din laptele A si imi ramane un timp tB = TIMP - tA de baut din laptele B
acea persoana nu o sa bea neaparat tot timpul din B
poate sa stea o vreme si fara sa faca nimic
d-aia apare div
adica eu ii zic astuia
tu trebuie sa bei NEAPARAT STRICT cantitatea Z de lapte A
dupa care bei cat timp mai poti din B
sa zic ca iti raman 10 secunde sa bei din B
si tu bei un litru in 4 secunde
mai bei 2 litri in 8 secunde si dupa aia a fost
nu bei 2,5 litri!
*/
int main()
{
fin >> N >> L;
for(int i = 1; i <= N; i++){
fin >> timp[i].A >> timp[i].B;
}
//caut binar T, pt ca raspuns(T) este monoton
int lo = 0;
int hi = LMAX * TIMPMAXIM * 2 + 1;
while(hi - lo > 1){
int mid = lo + (hi - lo) / 2;
int val = valid(mid);
if(val){
hi = mid;
}
else {
lo = mid;
}
}
//raspunsul se afla in hi
fout << hi << "\n";
int aux = valid(hi); //apelez valid de hi pt a crea v[][]
for(int i = 1; i <= N; i++){
fout << cantitate[i][RASPUNS].A << ' ' << cantitate[i][RASPUNS].B << "\n";
}
return 0;
}