Cod sursa(job #2206976)

Utilizator _Victor_Victor Ciobanu _Victor_ Data 24 mai 2018 17:37:08
Problema Ghiozdan Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.22 kb
#include <bits/stdc++.h>

using namespace std;

int g,G[2][75000],N[2][75000];
short V[20000];

ifstream fin("ghiozdan.in");
ofstream fout("ghiozdan.out");

void dpi(int i_f,int i_s,int j_s,int g){
	//cout<<"dpi:\n";
	for (int i=i_s-1;i>=i_f;i--){
			for (int j=j_s;j<=g-V[i];j++){
			 int p = j+V[i];
			 if(p<=g)
			 if(G[1][p]+V[i]>G[1][j] || (G[1][p]+V[i]==G[1][j] && N[1][p]+1<N[1][j])){
			 	 	G[1][j]=G[1][p]+V[i];
			 	 	N[1][j]=N[1][p]+1;
			 	}	
			}
			/*for(int j=j_s;j<=g;j++)
				cout<<G[1][j]<<' ';
			cout<<'\n';*/
	}
}


void dp(int i_s,int i_f,int j_s,int g){
//	cout<<"dp:\n";
	for (int i=i_s;i<i_f;i++){
			for (int j=g;j>=j_s;j--){
			 int p = j-V[i];
			 if (p>=j_s)
			 if(G[0][p]+V[i]>G[0][j] || (G[0][p]+V[i]==G[0][j] && N[0][p]+1<N[0][j])){
			 	 	G[0][j]=G[0][p]+V[i];
			 	 	N[0][j]=N[0][p]+1;
			 	}	 
			}
/*			for(int j=j_s;j<=g;j++)
				cout<<G[0][j]<<' ';
			cout<<'\n';*/
	}
}
void nul(int *p, int s,int f){
	for(int i=s;i<=f;i++) p[i]=0;
}
bool first = true;
void solve(int s,int n, int j_s,int g){
 if (n-s == 1 || n==s){
 	if(V[s]<=g-j_s) fout<<V[s]<<'\n';
 } else if(n>s && j_s<=g){
	//Initializarea tuturor datelor(tabelele si mijlocul)
	nul(G[0],j_s,g);
	nul(G[1],j_s,g);
	nul(N[0],j_s,g);
	nul(N[1],j_s,g);
	int m = (n-s)/2 + s;
	//Parcurgerea si rezolvarea cu ajutorul dp a tablourilor
	dp(s,m,j_s,g);
	dpi(m,n,j_s,g);
	//Sumarea celor doua linii de tabel si cautarea celui mai optim rezultat ce se va afla pe indicele imax
	int mx=0,nmin=0,imax=0;
//	cout<<"sum: ";
	for(int i=j_s;i<=g;i++){
			G[0][i]+=G[1][i];
			N[0][i]+=N[1][i];
//			cout<<G[0][i]<<' ';
			if(G[0][i]>mx||(G[0][i]==mx && N[0][i]<nmin)){
				mx=G[0][i];
				nmin=N[0][i];
				imax=i;
			}  
		}
//		cout<<" imax = "<<imax<<'\n';
		//In cazul in care rezultatul e gasit prima oara atunci scriem tot in fisier
		if (first){
			//cout<<mx<<' '<<nmin<<'\n';
			fout<<mx<<' '<<nmin<<'\n';
			first=false;
			}
		//"Feliem" tabelul in 4 si prelucram coltul de dreapta-sus si stanga-jos
		if (mx){
			solve(s,m,j_s,imax);
			solve(m,n,imax,g);
		}
	}
}
int main(){
	int n;
	fin>>n>>g;
	for (int i=0;i<n;i++)
	fin>>V[i];
	solve(0,n,0,g);
//	dp(0,n,0,g);
	return 0;
}