Bergur*
Last updated
Last updated
The goal is to minimize the total cost while processing the list. The cost is determined by the value of the minimum element in each segment multiplied by the number of elements in that segment. The greedy strategy works as follows:
Identify the Local Minimum (Low Point):
At each step, find the smallest element in the current range of the list ([start, end]
).
This ensures that the cost for the current segment is minimized, as the lowest element dominates the cost for that segment.
Calculate the Cost for the Current Segment:
Use the identified local minimum to calculate the cost for the current segment, which includes all elements from start
to the local minimum index (low_pt_index
).
Update the Remaining Range:
After processing the current segment, move start
to the next index after the local minimum (low_pt_index + 1
).
Repeat the process for the remaining range of the list.
Stop When the Entire List is Processed:
The algorithm terminates when the start
index exceeds end
, meaning all elements have been processed.
The cost for this segment is: cost=min_value×(low_pt_index−start+1)
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 32
static
int skip_space() {
int c;
do {
c = fgetc(stdin);
} while (isspace(c) && c != EOF);
return c;
}
static
size_t fill_buffer(char *buf, size_t len) {
int c;
size_t i = 0;
while (1) {
c = fgetc(stdin);
if (c == EOF || isspace(c)) {
buf[i] = 0;
return i + 1;
}
buf[i] = (char)c;
i = i + 1;
if (i == len) {
return i;
}
}
}
/**
* @brief Read and return a string from standard input (until
* we reach a spa
*
* @return The string read if successful. The caller is
* responsible for freeing the memory allocated to the string.
* Return NULL if an error is encountered when reading.
*
* @note Based on FIO20-C. Avoid unintentional truncation when
* using fgets() or fgetws()
* https://wiki.sei.cmu.edu/
*/
char* cs1010_read_word()
{
char buf[BUF_SIZE];
char *ret = malloc(1);
if (ret == NULL) {
return NULL;
}
size_t total_len = 1;
size_t len;
int c = skip_space();
if (c == EOF) {
free(ret);
printf("EOF encountered. return NULL\n");
return NULL;
}
*ret = (char)c;
do {
len = fill_buffer(buf, BUF_SIZE);
char *temp = realloc(ret, total_len + len + 1);
if (temp == NULL) {
free(ret);
return NULL;
}
ret = temp;
memcpy(ret + total_len, buf, len); // concat the string
total_len += len;
} while (len == BUF_SIZE && buf[len-1] != 0);
return ret;
}
/**
* @brief Read and return a long int from standard input.
*
* @details Based on INT05-C from SEI CERT C Coding Standard
* https://wiki.sei.cmu.edu/
*
* @return the value read if successful. Return LONG_MAX
* with an error message printed if an error occured.
*/
long cs1010_read_long()
{
char *buff;
char *end_ptr;
long number;
buff = cs1010_read_word();
if (buff == NULL) {
fprintf(stderr, "cs1010_read_long: EOF or read error\n");
return LONG_MAX;
}
errno = 0;
number = strtol(buff, &end_ptr, 10);
if (ERANGE == errno) {
fprintf(stderr, "cs1010_read_long: number '%s' out of range\n", buff);
free(buff);
return LONG_MAX;
}
if (end_ptr == buff) {
fprintf(stderr, "cs1010_read_long: '%s' is not a valid numeric input\n", buff);
free(buff);
return LONG_MAX;
}
if ('\n' != *end_ptr && '\0' != *end_ptr) {
fprintf(stderr, "cs1010_read_long: reach the end without null/newline. '%s' remains\n", end_ptr);
free(buff);
return LONG_MAX;
}
free(buff);
return number;
}
/**
* @brief Read and return a string from standard input (until
* we reach the new line.)
*
* @return the string read if successful. The caller is
* responsible for freeing the memory allocated to the string.
* Return NULL if an error is encountered when reading.
*
* @note See FIO20-C. Avoid unintentional truncation when using fgets() or fgetws()
* https://wiki.sei.cmu.edu/
*/
char* cs1010_read_line()
{
char* buf = NULL;
size_t dummy = 0;
if (getline(&buf, &dummy, stdin) == -1) {
fprintf(stderr, "cs1010_read_line: unable to read line into buffer\n");
return NULL;
}
return buf;
}
/**
* @brief Read and return a double from standard input.
*
* @return the value read if successful. Return DOUBLE_MAX
* with an error message printed if an error occured.
*/
double cs1010_read_double()
{
char *buff;
char *end_ptr;
double number;
buff = cs1010_read_word();
if (buff == NULL) {
fprintf(stderr, "cs1010_read_double: EOF or read error\n");
return DBL_MAX;
}
errno = 0;
number = strtod(buff, &end_ptr);
if (ERANGE == errno) {
free(buff);
fprintf(stderr, "cs1010_read_double: number '%s' out of range\n", buff);
return DBL_MAX;
}
if (end_ptr == buff) {
free(buff);
fprintf(stderr, "cs1010_read_double: '%s' is not a valid numeric input\n", buff);
return DBL_MAX;
}
if ('\n' != *end_ptr && '\0' != *end_ptr) {
free(buff);
fprintf(stderr, "cs1010_read_double: reach the end without null/newline. '%s' remains\n", buff);
return DBL_MAX;
}
free(buff);
return number;
}
/**
* @brief Read and return multiple long int from standard
* input into an array.
*
* @return The array read if successful. The caller is responsible
* for freeing the array. Return NULL if an error occured.
*/
long* cs1010_read_long_array(size_t how_many)
{
long *buffer = calloc(how_many, sizeof(long));
if (buffer == NULL) {
return NULL;
}
for (size_t i = 0; i < how_many; i = i + 1) {
buffer[i] = cs1010_read_long();
}
return buffer;
}
/**
* @brief Read and return multiple double from standard
* input into an array.
*
* @return The array read if successful. The caller is responsible
* for freeing the array. Return NULL if an error occured.
*/
double* cs1010_read_double_array(size_t how_many)
{
double *buffer = calloc(how_many, sizeof(double));
if (buffer == NULL) {
return NULL;
}
for (size_t i = 0; i < how_many; i = i + 1) {
buffer[i] = cs1010_read_double();
}
return buffer;
}
/**
* @brief Read and return multiple lines from standard
* input into an array.
*
* @return The array read if successful. The caller is responsible
* for freeing the array and each string in the array. Return NULL
* if an error occured.
*/
char** cs1010_read_line_array(size_t how_many)
{
char **buffer = calloc(how_many, sizeof(char*));
if (buffer == NULL) {
return NULL;
}
for (size_t i = 0; i < how_many; i = i + 1) {
buffer[i] = cs1010_read_line();
if (buffer[i] == NULL) {
for (size_t j = 0; j < i; j = j + 1) {
free(buffer[j]);
}
free(buffer);
return NULL;
}
}
return buffer;
}
/**
* @brief Read and return multiple space-delimited words
* from standard input into an array.
*
* @return The array read if successful. The caller is
* responsible for freeing the array and each string in
* the array. Return NULL if an error occured.
*/
char** cs1010_read_word_array(size_t how_many)
{
char **buffer = calloc(how_many, sizeof(char*));
if (buffer == NULL) {
return NULL;
}
for (size_t i = 0; i < how_many; i = i + 1) {
buffer[i] = cs1010_read_word();
if (buffer[i] == NULL) {
for (size_t j = 0; j < i; j = j + 1) {
free(buffer[j]);
}
free(buffer);
return NULL;
}
}
return buffer;
}
/**
* @brief Read a size_t value from the standard input.
* Reporting an error and return 0 instead of the value
* is less than 0..
*/
size_t cs1010_read_size_t() {
char *buff;
char *end_ptr;
unsigned long number;
buff = cs1010_read_word();
if (buff == NULL) {
fprintf(stderr, "cs1010_read_size_t: EOF or read error\n");
return SIZE_MAX;
}
errno = 0;
number = strtoul(buff, &end_ptr, 10);
if (ERANGE == errno) {
fprintf(stderr, "cs1010_read_size_t: number '%s' out of range of unsigned long\n", buff);
free(buff);
return SIZE_MAX;
}
if (end_ptr == buff) {
fprintf(stderr, "cs1010_read_size_t: '%s' is not a valid numeric input\n", buff);
free(buff);
return SIZE_MAX;
}
if ('\n' != *end_ptr && '\0' != *end_ptr) {
fprintf(stderr, "cs1010_read_size_t: reach the end without null/newline. '%s' remains\n", end_ptr);
free(buff);
return SIZE_MAX;
}
if (number > SIZE_MAX) {
fprintf(stderr, "cs1010_read_size_t: number '%s' out of range of size_t\n", buff);
free(buff);
return SIZE_MAX;
}
free(buff);
return number;
}
/**
* @brief Print a double to standard output with format %.4f.
*/
void cs1010_print_double(double d)
{
printf("%.4f", d);
}
/**
* @brief Print a long to standard output with format %.4f.
*/
void cs1010_print_long(long d)
{
printf("%ld", d);
}
/**
* @brief Print a double to standard output with format %.4f,
* followed by a newline.
*/
void cs1010_println_double(double d)
{
cs1010_print_double(d);
printf("\n");
}
/**
* @brief Print a long to standard output with format %.4f, followed by a newline.
*/
void cs1010_println_long(long d)
{
cs1010_print_long(d);
printf("\n");
}
/**
* @brief Print a string to standard output.
*/
void cs1010_print_string(char *s)
{
printf("%s", s);
}
/**
* @brief Print a string to standard output, followed by a newline.
*/
void cs1010_println_string(char *s)
{
printf("%s\n", s);
}
/**
* @brief Print a pointer to standard output.
*/
void cs1010_print_pointer(void *ptr)
{
cs1010_print_long((long)ptr);
}
/**
* @brief Print a pointer to standard output, followed by a newline.
*/
void cs1010_println_pointer(void *ptr)
{
cs1010_println_long((long)ptr);
}
/**
* @brief Print a size_t to standard output with format %zu.
*/
void cs1010_print_size_t(size_t d)
{
printf("%zu", d);
}
/**
* @brief Print a size_t to standard output with format %zu.
*/
void cs1010_println_size_t(size_t d)
{
printf("%zu\n", d);
}
/**
* @brief Print a bool to standard output with format %zu.
*/
void cs1010_print_bool(bool b)
{
if (b) {
printf("true");
} else {
printf("false");
}
}
/**
* @brief Print a bool to standard output with format %zu.
*/
void cs1010_println_bool(bool b)
{
if (b) {
printf("true\n");
} else {
printf("false\n");
}
}
/**
* @brief Clear the screen.
*/
void cs1010_clear_screen()
{
printf("[2J[;H");
}
long find_low_point(long *a, long start, long end) {
long min_index = start;
for (long i = start + 1; i <= end; i++) {
if (a[i] < a[min_index]) {
min_index = i;
}
}
return min_index;
}
int main()
{
size_t n = cs1010_read_size_t();
long *num = cs1010_read_long_array(n);
if (num == NULL)
{
return 1;
}
long sum = 0;
long start = 0;
long end = (long)n - 1;
while (start <= end)
{
long low_pt_index = find_low_point(num, start, end);
sum += num[low_pt_index] * (low_pt_index - start + 1);
start = low_pt_index + 1;
}
cs1010_println_long(sum);
free(num);
}