Cod sursa(job #1995816)

Utilizator CristiChCristi Chindris CristiCh Data 29 iunie 2017 10:30:09
Problema Problema rucsacului Scor 0
Compilator c Status done
Runda Arhiva educationala Marime 22.3 kb
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define N	6
#define M	7

//QuickSort

//void StoreInputTo(int *v);
//void QuickSort(int *v, int left, int right);
//int Partition(int *v, int left, int right);
//void Swap(int value_1, int value_2, int *v);
//
//int main() {
//	int v[N];
//	StoreInputTo(v);
//	QuickSort(v, 0, N - 1);
//	
//	for (int i = 0; i < N; i++) {
//		printf("%d ", v[i]);
//	}
//}
//void StoreInputTo(int *v) {
//	for (int i = 0; i < N; i++) {
//		scanf("%d", &v[i]);
//	}
//}
//void QuickSort(int *v, int left, int right) {
//	if (left >= right) return;
//	int split_point = Partition(v, left, right);
//	QuickSort(v, left, split_point - 1);
//	QuickSort(v, split_point + 1, right);
//}
//int Partition(int *v, int left, int right) {
//	int pivot = left, pivot_value = v[pivot];
//	while (left < right) {
//		while (v[left] <= pivot_value) left++;
//		while (v[right] > pivot_value) right--;
//		if (left < right) {
//			Swap(left, right, v);
//		}
//	}
//	Swap(pivot, right, v);
//	return right;
//}
//void Swap(int value_1, int value_2, int *v) {
//	int aux = v[value_1];
//	v[value_1] = v[value_2], v[value_2] = aux;
//}

//MergeSort

//void StoreInputTo(int *v);
//void MergeSort(int *v, int left, int right);
//void Merge(int *v, int left, int middle, int right);
//
//int main() {
//	int v[N];
//	StoreInputTo(v);
//	MergeSort(v, 0, N - 1);
//
//	for (int i = 0; i < N; i++) {
//		printf("%d ", v[i]);
//	}
//}
//void StoreInputTo(int *v) {
//	for (int i = 0; i < N; i++) {
//		scanf("%d", &v[i]);
//	}
//}
//void MergeSort(int *v, int left, int right) {
//	if (left >= right) return;
//	int middle = (left + right) / 2;
//	MergeSort(v, left, middle);
//	MergeSort(v, middle + 1, right);
//	Merge(v, left, middle, right);
//}
//void Merge(int *v, int left, int middle, int right) {
//	int *result = (int*)malloc((right - left + 1) * sizeof(int));
//	int i = left, j = middle + 1, k = 0;
//	while (i <= middle && j <= right) {
//		if (v[i] < v[j]) {
//			result[k++] = v[i++];
//		}
//		else {
//			result[k++] = v[j++];
//		}
//	}
//	while (i <= middle) {
//		result[k++] = v[i++];
//	}
//	while (j <= right) {
//		result[k++] = v[j++];
//	}
//	for (int p = 0; p <= right - left; p++) {
//		v[left + p] = result[p];
//	}
//}

//Examen TP Septembrie 2015
//Subiectul 1

//void ReadValues(int *values);
//int VerifyBeautifullIndexion(int *values, int left, int right);
//int FindLonelyNumber(int *values, int left, int right);
//
//void main() {
//	int values[N];
//	ReadValues(values);
//	//a
//	int index = VerifyBeautifullIndexion(values, 0, N - 1);
//	if (index >= 0)
//		printf("%d ", index);
//	else
//		printf("Vectorul nu este frumos indexat.");
//	//b - Subiectul 2
//	//int number = FindLonelyNumber(values, 0, N - 1);
//	//printf("%d ", number);
//}
//
//void ReadValues(int *values) {
//	for (int i = 0; i < N; i++)
//		scanf("%d", &values[i]);
//}
//int VerifyBeautifullIndexion(int *values, int left, int right) {
//	int m = (left + right) / 2;
//	if (values[m] == m) return m;
//	if (left == right) return -1;
//	if (values[m] > m) VerifyBeautifullIndexion(values, left, m - 1);
//	else VerifyBeautifullIndexion(values, m + 1, right);
//}
//int FindLonelyNumber(int *values, int left, int right) {
//	int m = (left + right) / 2;
//	if (values[m] == values[m + 1]) {
//		if ((right - m - 1) % 2 == 0) {
//			FindLonelyNumber(values, left, m - 1);
//		}
//		else {
//			FindLonelyNumber(values, m + 2, right);
//		}
//	}
//	else if (values[m] == values[m - 1]) {
//		if ((right - m) % 2 == 0) {
//			FindLonelyNumber(values, left, m - 2);
//		}
//		else {
//			FindLonelyNumber(values, m + 1, right);
//		}
//	}
//	else
//		return values[m];
//}

//Subiectul 1

//int m, n, k;
//int matrice[100];
//int solutie[100];
//
//char *Citire_matrice();
//void backtracking(char *k_ch, int pos, char *to_ver, int vector_int);
//char *concatenare_string(int *sol, int count, int x, char *k, int *pos);
//bool verificare(char *to_ver, int pos, char *k_ch);
//
//void main() {
//	char *k_ch = Citire_matrice();
//	char *to_ver = NULL;
//	backtracking(k_ch, 0, to_ver, 0);
//}
//
//char *Citire_matrice() {
//	scanf("%d %d %d", &m, &n, &k);
//	for (int i = 0; i < m*n; i++) {
//		scanf("%d", &matrice[i]);
//	}
//	char *result = (char*)malloc(sizeof(char) * 100);
//	snprintf(result, 100, "%d", k);
//	return result;
//}
//void backtracking(char *k_ch, int pos, char *to_ver, int vector_int) {
//	for (int i = 0; i < m*n; i++) {
//		to_ver = concatenare_string(solutie, vector_int, matrice[i], to_ver, &pos);
//		if (verificare(to_ver, pos, k_ch)) {
//			solutie[vector_int] = matrice[i];
//			if (strcmp(to_ver, k_ch) == 0) {
//				printf("\n");
//				for (int j = 0; j <= vector_int; j++)
//					printf("%d ", solutie[j]);
//				return;
//			}
//			else {
//				backtracking(k_ch, pos, to_ver, vector_int + 1);
//			}
//		}
//	}
//}
//char *concatenare_string(int *sol, int count, int x, char *k, int *pos) {
//	char *result = (char*)malloc(100);
//	char *str = (char*)malloc(100);
//	if (count == 0) {
//		snprintf(result, 100, "%d", x);
//	}
//	else {
//		snprintf(str, 100, "%d", sol[0]);
//		strcpy(result, str);
//		for (int i = 1; i < count; i++) {
//			snprintf(str, 100, "%d", sol[i]);
//			strcat(result, str);
//		}
//		snprintf(str, 100, "%d", x);
//		strcat(result, str);
//	}
//	(*pos) = strlen(result);
//	return result;
//}
//bool verificare(char *to_ver, int pos, char *k_ch) {
//	for (int i = 0; i < pos; i++)
//		if (to_ver[i] != k_ch[i])
//			return false;
//	return true;
//}

//Subiectul 2

//char s[100];
//
//int Numara_subsiruri();
//bool verificare(int i, int j);
//
//void main() {
//	scanf("%s", s);
//	printf("%d", Numara_subsiruri());
//}
//int Numara_subsiruri() {
//	int result = 0;
//	int n = strlen(s);
//	for (int i = 0; i < n; i++) {
//		for (int j = i; j < n; j++)
//			if (verificare(i, j))
//				result++;
//	}
//	return result-n;
//}
//bool verificare(int i, int j) {
//	for (int k = i; k < j/2; k++) {
//		if (s[k] != s[j - k])
//			return false;
//	}
//	return true;
//}

//Backtracking
//Exercitiul 1

//void ReadInput(int *n);
//void Run(int n);
//void SolveSquare(int n, int *solution, int count);
//bool IsSolution(int *solution, int count, int n);
//void PrintSolution(int *solution, int count, int n);
//bool IsValid(int *solution, int count, int n);
//void SolveNaturalDistinct(int n, int *solution, int count);
//void SolvePrimeDistinct(int n, int *solution, int count);
//bool IsPrime(int no);
//
//int main() {
//	int n;
//	ReadInput(&n);
//	Run(n);
//}
//void ReadInput(int *n) {
//	printf("Introduceti numarul n: ");
//	scanf("%d", n);
//}
//void Run(int n) {
//	int solution[50];
//	//SolveSquare(n, solution, 0);
//	//SolveNaturalDistinct(n, solution, 0);
//	SolvePrimeDistinct(n, solution, 0);
//}
//void SolveSquare(int n, int *solution, int count) {
//	for (int i = 1; i*i <= n; i++) {
//		solution[count] = i*i;
//		if (IsValid(solution, count, n)) {
//			if (IsSolution(solution, count, n)) {
//				PrintSolution(solution, count, n);
//			}
//			else
//				SolveSquare(n, solution, count + 1);
//		}
//	}
//}
//bool IsSolution(int *solution, int count, int n) {
//	int result = 0;
//	for (int i = 0; i <= count; i++) {
//		result += solution[i];
//	}
//	if (result == n)
//		return true;
//	else
//		return false;
//}
//void PrintSolution(int *solution, int count, int n) {
//	printf("\n%d = ", n);
//	for (int i = 0; i <= count; i++) {
//		printf("%d ", solution[i]);
//		if (i < count)
//			printf("+ ");
//	}
//}
//bool IsValid(int *solution, int count, int n) {
//	int result = 0;
//	for (int i = 0; i <= count; i++) {
//		result += solution[i];
//	}
//	if (result <= n)
//		return true;
//	else
//		return false;
//}
//void SolveNaturalDistinct(int n, int *solution, int count) {
//	for (int i = count + 1; i < n; i++) {
//		solution[count] = i;
//		if ((solution[count] != solution[count-1]) && IsValid(solution, count, n)) {
//			if (IsSolution(solution, count, n)) {
//				PrintSolution(solution, count, n);
//			}
//			else
//				SolveNaturalDistinct(n, solution, count + 1);
//		}
//	}
//}
//void SolvePrimeDistinct(int n, int *solution, int count) {
//	for (int i = count + 1; i < n; i++) {
//		if (IsPrime(i)) {
//			solution[count] = i;
//			if ((solution[count] != solution[count - 1]) && IsValid(solution, count, n)) {
//				if (IsSolution(solution, count, n)) {
//					PrintSolution(solution, count, n);
//				}
//				else
//					SolveNaturalDistinct(n, solution, count + 1);
//			}
//		}
//	}
//}
//bool IsPrime(int no) {
//	for (int i = 2; i < no; i++) {
//		if (no % i == 0)
//			return false;
//	}
//	return true;
//}

//Generarea tuturor sortarilor topologice pentru un graf orientat

//int total;
//
//void StoreInputTo(int graph[N][N], int *ranks);
//void ReachEveryTopSort(int graph[N][N], int *ranks, bool *visited, int *solution, int count);
//void DeletePathsFrom(int current, int *ranks, int graph[N][N]);
//void PrintSolution(int *solution);
//void RestorePathsFrom(int current, int *ranks, int graph[N][N]);
//
//int main() {
//	int graph[N][N], ranks[N], solution[N];
//	bool visited[N] = { false };
//	StoreInputTo(graph, ranks);
//	ReachEveryTopSort(graph, ranks, visited, solution, 0);
//	printf("%d\n", total);
//}
//void StoreInputTo(int graph[N][N], int *ranks) {
//	for (int i = 0; i < N; i++) {
//		for (int j = 0; j < N; j++) {
//			scanf("%d", &graph[i][j]);
//		}
//	}
//	for (int i = 0; i < N; i++) {
//		scanf("%d", &ranks[i]);
//	}
//}
//void ReachEveryTopSort(int graph[N][N], int *ranks, bool *visited, int *solution, int count) {
//	for (int i = 0; i < N; i++) {
//		if (ranks[i] == 0) {
//			if (visited[i] == false) {
//				visited[i] = true;
//				solution[count] = i;
//				DeletePathsFrom(i, ranks, graph);
//				if (count == N - 1) {
//					PrintSolution(solution);
//					total++;
//				}
//				else {
//					ReachEveryTopSort(graph, ranks, visited, solution, count + 1);
//				}
//				RestorePathsFrom(i, ranks, graph);
//				visited[i] = false;
//			}
//		}
//	}
//}
//void DeletePathsFrom(int current, int *ranks, int graph[N][N]) {
//	for (int i = 0; i < N; i++) {
//		if (graph[current][i] == 1)
//			ranks[i]--;
//	}
//}
//void PrintSolution(int *solution) {
//	for (int i = 0; i < N; i++) {
//		printf("%d ", solution[i]);
//	}
//	printf("\n");
//}
//void RestorePathsFrom(int current, int *ranks, int graph[N][N]) {
//	for (int i = 0; i < N; i++) {
//		if (graph[current][i] == 1)
//			ranks[i]++;
//	}
//}

/*Se citesc din fisierul fazan.in numerele naturale n, si m (n<=15, m<=n) si apoi n cuvinte distincte cu cel mult 10 litere fiecare.
Sa se afiseze toate secvente de cate m cuvinte dintre cele citite care sa respecte conditiile jocului "fazan". */

//void StoreInputTo(int *n, int *m, char words[][11]);
//void PlayFazan(int n, int m, char words[][11], char solution[][11], int count);
//bool IsValid(int count, int m, char solution[][11]);
//void PrintSolution(char solution[][11], int count);
//
//int main() {
//	int n, m;
//	char words[15][11], solution[3][11];
//	StoreInputTo(&n, &m, words);
//	PlayFazan(n, m, words, solution, 0);
//}
//void StoreInputTo(int *n, int *m, char words[][11]) {
//	scanf("%d %d", n, m);
//	for (int i = 0; i < *n; i++) {
//		scanf("%s", words[i]);
//	}
//}
//void PlayFazan(int n, int m, char words[][11], char solution[][11], int count) {
//	for (int i = 0; i < n; i++) {
//		strcpy(solution[count], words[i]);
//		if (IsValid(count, m, solution)) {
//			if (count == m - 1) {
//				PrintSolution(solution, count);
//			}
//			else {
//				PlayFazan(n, m, words, solution, count + 1);
//			}
//		}
//	}
//}
//bool IsValid(int count, int m, char solution[][11]) {
//	if (count <= m) {
//		if (count >= 1) {
//			if (solution[count - 1][0] == solution[count][0])
//				return false;
//			int lenght_1 = strlen(solution[count - 1]);
//			if (solution[count - 1][lenght_1 - 2] == solution[count][0] && solution[count - 1][lenght_1 - 1] == solution[count][1])
//				return true;
//		}
//		else {
//			return true;
//		}
//	}
//	return false;
//}
//void PrintSolution(char solution[][11], int count) {
//	for (int i = 0; i <= count; i++) {
//		printf("%s ", solution[i]);
//	}
//	printf("\n");
//}

//Sudoku

//int sudoku_matrix_ver[N][N];
//int sudoku_matrix[N][N];
//
//void StoreInput();
//void Backtracking(int line, int col);
//bool IsValid(int line, int col, int element);
//bool IsOk(int line, int col, int element, int line_from, int line_to, int col_from, int col_to);
//void Print();
//
//int main() {
//	StoreInput();
//	Backtracking(0, 0);
//}
//void StoreInput() {
//	for (int i = 0; i < N; i++) {
//		for (int j = 0; j < N; j++) {
//			scanf("%d", &sudoku_matrix[i][j]);
//		}
//	}
//}
//void Backtracking(int line, int col) {
//	if ( line == N && col == 0) {
//		Print();
//	}
//	if (sudoku_matrix[line][col]) {
//		sudoku_matrix_ver[line][col]= sudoku_matrix[line][col];
//		if (col == N - 1) {
//			Backtracking(line + 1, 0);
//			sudoku_matrix_ver[line + 1][col] = 0;
//		}
//		else {
//			Backtracking(line, col + 1);
//			sudoku_matrix_ver[line][col + 1] = 0;
//		}
//	}
//	else {
//		for (int i = 1; i <= N; i++) {
//			sudoku_matrix_ver[line][col] = i;
//			if (IsValid(line, col, i)) {
//				if (col == N - 1) {
//					Backtracking(line + 1, 0);
//					sudoku_matrix_ver[line + 1][col] = 0;
//				}
//				else {
//					Backtracking(line, col + 1);
//					sudoku_matrix_ver[line][col + 1] = 0;
//				}
//			}
//		}
//	}
//
//}
//bool IsValid(int line, int col, int element) {
//	for (int i = 0; i < N; i++) {
//		if (i != col)
//			if (sudoku_matrix_ver[line][i] == element || sudoku_matrix[line][i] == element)
//				return false;
//		if (i != line)
//			if (sudoku_matrix_ver[i][col] == element || sudoku_matrix[i][col] == element)
//				return false;
//	}
//	if (col < 3) {
//		if (line < 3) {
//			return IsOk(line, col, element, 0, 3, 0, 3);
//		}
//		if (line < 6) {
//			return IsOk(line, col, element, 3, 6, 0, 3);
//		}
//		if (line < 9) {
//			return IsOk(line, col, element, 6, 9, 0, 3);
//		}
//	}
//	if (col < 6) {
//		if (line < 3) {
//			return IsOk(line, col, element, 0, 3, 3, 6);
//		}
//		if (line < 6) {
//			return IsOk(line, col, element, 3, 6, 3, 6);
//		}
//		if (line < 9) {
//			return IsOk(line, col, element, 6, 9, 3, 6);
//		}
//	}
//	if (col < 9) {
//		if (line < 3) {
//			return IsOk(line, col, element, 0, 3, 6, 9);
//		}
//		if (line < 6) {
//			return IsOk(line, col, element, 3, 6, 6, 9);
//		}
//		if (line < 9) {
//			return IsOk(line, col, element, 6, 9, 6, 9);
//		}
//	}
//}
//bool IsOk(int line, int col, int element, int line_from, int line_to, int col_from, int col_to) {
//	for (int i = line_from; i < line_to; i++) {
//		for (int j = col_from; j < col_to; j++) {
//			if (i != line && j != col)
//				if (sudoku_matrix[i][j] == element || sudoku_matrix_ver[i][j] == element)
//					return false;
//		}
//	}
//	return true;
//}
//void Print(){
//	for (int i = 0; i < N; i++) {
//		for (int j = 0; j < N; j++) {
//			printf("%d ", sudoku_matrix_ver[i][j]);
//		}
//		printf("\n");
//	}
//	printf("\n\n");
//}

//Branch and Bound
/*Se considera n persoane si n joburi. O matrice de costuri pentru fiecare cuplu.
Se cere o asociere bijectiva intre persoane si joburi astfel incat costul acestor asocieri sa fie minim.*/

//int init_cost, branch_cost;
//
//void StoreInputTo(int costs[N][N]);
//bool FindMinCost(int costs[N][N], bool *checked, int count);
//int SelectMin(int costs[N][N], bool *checked, int count, int *index, int cost);
//void BranchAndBound(int costs[N][N], bool *checked, int *solution, int count);
//bool IsValid(int costs[N][N], bool *checked, int count, int index);
//
//int main() {
//	int costs[N][N], solution[N];
//	bool checked[N] = { false };
//	StoreInputTo(costs);
//	FindMinCost(costs, checked, 0);
//	printf("Greedy cost: %d\n", init_cost);
//	for (int i = 0; i < N; i++) {
//		checked[i] = false;
//	}
//	BranchAndBound(costs, checked, solution, 0);
//	printf("Branch and Bound cost: %d\n", init_cost);
//	return 0;
//}
//void StoreInputTo(int costs[N][N]) {
//	for (int i = 0; i < N; i++) {
//		for (int j = 0; j < N; j++) {
//			scanf("%d", &costs[i][j]);
//		}
//	}
//}
//bool FindMinCost(int costs[N][N], bool *checked, int count) {
//	if (count == N)
//		return true;
//	int index = 0, minim = SelectMin(costs, checked, count, &index, init_cost);
//	checked[index] = true, init_cost += minim;
//	if (FindMinCost(costs, checked, count + 1))
//		return true;
//}
//int SelectMin(int costs[N][N], bool *checked, int count, int *index, int cost) {
//	int result = INT_MAX;
//	for (int i = 0; i < N; i++) {
//		if(!checked[i])
//			if (costs[count][i] <= result) {
//				result = costs[count][i];
//				(*index) = i;
//			}
//	}
//	return result;
//}
//void BranchAndBound(int costs[N][N], bool *checked, int *solution, int count) {
//	if (count == N) {
//		if (branch_cost < init_cost)
//			init_cost = branch_cost;
//		return;
//	}
//	for (int i = 0; i < N; i++) {
//		solution[count] = i;
//		if (IsValid(costs, checked, count, i)) {
//			checked[i] = true, branch_cost += costs[count][i];
//			BranchAndBound(costs, checked, solution, count + 1);
//			checked[i] = false, branch_cost -= costs[count][i];
//		}
//	}
//}
//bool IsValid(int costs[N][N], bool *checked, int count, int index) {
//	if (checked[index] == true)
//		return false;
//	if (branch_cost + costs[count][index] > init_cost)
//		return false;
//	return true;
//}

/*Pe o linie de cale ferata se gasesc n vagoane numerotate diferit intr-o ordine aleatoare. O macara poate lua maxim k vagoane si sa le mute la final.
Se cere numarul minim de mutari pe care trebuie sa le efectueze macaraua stiind ordinea lor initiala.*/

//int moves;
//
//void StoreInputTo(int *order);
//void BranchAndBound(int *order);
//bool IsSolution(int *vector);
//void BackTracking(int *source, int *solution);
//int CreateNewOrder(int *destination, int *source, int from_value, int values_no);
//
//int main() {
//	int order[N];
//	StoreInputTo(order);
//	BranchAndBound(order);
//	printf("%d\n", moves);
//}
//
//void StoreInputTo(int *order) {
//	for (int i = 0; i < N; i++) {
//		scanf("%d", &order[i]);
//	}
//}
//void BranchAndBound(int *vector) {
//	int solution[N];
//	if (IsSolution(vector))
//		return;
//	BackTracking(vector, solution);
//	BranchAndBound(solution);
//}
//bool IsSolution(int *order) {
//	for (int i = 1; i < N; i++) {
//		if (order[i] != (order[i - 1] + 1))
//			return false;
//	}
//	return true;
//}
//void BackTracking(int *source, int *solution) {
//	int min_consecutive_parts = 6, aux[N];
//	for (int count = 1; count < N; count++) {
//		for (int i = 0; i < N - 1; i++) {
//			if (count + i <= N - 1) {
//				int p = CreateNewOrder(aux, source, i, count);
//				if (p < min_consecutive_parts) {
//					min_consecutive_parts = p, CreateNewOrder(solution, aux, 0, 0);
//				}
//			}
//		}
//	}
//	moves++;
//}
//int CreateNewOrder(int *destination, int *source, int from_value, int values_no) {
//	for (int i = 0; i < values_no; i++) {
//		destination[N - values_no + i] = source[from_value + i];
//	}
//	for (int i = 0; i < from_value; i++) {
//		destination[i] = source[i];
//	}
//	for (int i = from_value; i < N - values_no; i++) {
//		destination[i] = source[i + values_no];
//	}
//	int result = 1;
//	for (int i = 1; i < N; i++) {
//		if (destination[i] != (destination[i - 1] + 1))
//			result++;
//	}
//	return result;
//}

//Programare dinamica
/*Se consideră o clădire de formă dreptunghiulară formată din n*m camere, dispuse pe n linii și m coloane.
Din orice cameră (i,j) se poate ajunge numai în camerele (i+1,j) sau (i,j+1), dacă aceasta nu este închisă.
Determinați în câte moduri se poate ajunge din camera (1,1) în camera (n,m).*/

//void StoreInput(int rooms[N][M]);
//int Count(int rooms[N][M]);
//void InitializeSolution(int solution[N][M], int rooms[N][M]);
//int ComputeSolution(int solution[N][M], int rooms[N][M]);
//
//int main() {
//	int rooms[N][M];
//	StoreInput(rooms);
//	printf("%d\n", Count(rooms));
//}
//void StoreInput(int rooms[N][M]) {
//	for (int i = 0; i < N; i++) {
//		for (int j = 0; j < M; j++) {
//			scanf("%d", &rooms[i][j]);
//		}
//	}
//}
//int Count(int rooms[N][M]) {
//	int solution[N][M], result = 0;
//	InitializeSolution(solution, rooms);
//	result = ComputeSolution(solution, rooms);
//	return result % 9901;
//}
//void InitializeSolution(int solution[N][M], int rooms[N][M]) {
//	for (int i = M - 1, k = 1; i >= 0; i--) {
//		if (rooms[N - 1][i] > 0) {
//			k = 0;
//		}
//		solution[N - 1][i] = k;
//	}
//	for (int i = N - 1, k = 1; i >= 0; i--) {
//		if (rooms[i][M - 1] > 0) {
//			k = 0;
//		}
//		solution[i][M - 1] = k;
//	}
//}
//int ComputeSolution(int solution[N][M], int rooms[N][M]) {
//	for (int i = N - 2; i >= 0; i--) {
//		for (int j = M - 2; j >= 0; j--) {
//			solution[i][j] = (!rooms[i][j]) ? (solution[i + 1][j] + solution[i][j + 1]) : 0;
//		}
//	}
//	return solution[0][0];
//}

/*Problema rucsacului*/

void StoreInput(int *objects, int *max_weight, int **weights, int **profits);
int MaxProfit(int objects, int max_weight, int *weights, int *profits);
int MaxValue(int a, int b);

int main() {
	int objects, max_weight, *weights, *profits;
	StoreInput(&objects, &max_weight, &weights, &profits);
	printf("%d\n", MaxProfit(objects, max_weight, weights, profits));
}
void StoreInput(int *objects, int *max_weight, int **weights, int **profits) {
	scanf("%d %d", objects, max_weight);
	(*weights) = (int*)malloc(sizeof(int)*(*objects)), (*profits) = (int*)malloc(sizeof(int)*(*objects));
	for (int i = 0; i < (*objects); i++) {
		scanf("%d %d", &(*weights)[i], &(*profits)[i]);
	}
}
int MaxProfit(int objects, int max_weight, int *weights, int *profits) {
	int *V = (int*)calloc(max_weight, sizeof(int));
	for (int i = 0; i < objects; i++) {
		for (int j = max_weight; j >= weights[i]; j--) {
			V[j] = MaxValue(V[j], V[j - weights[i]] + profits[i]);
		}
	}
	return V[max_weight];
}
int MaxValue(int a, int b) {
	if (a > b)
		return a;
	return b;
}