Problem 1_03_guess

一道题目,原题完整叙述如下:

(在论坛里面发了一个帖子:http://topic.csdn.net/u/20110717/15/43b31571-56f1-4657-a987-3dd4d4ce1bdd.html?seed=1334194431&r=74470922#r_74470922

Description

A competition was just over. It had 3 problems and n players. Eachplayer had an ID number from 1 to n. The final rank wasdecided by the total score of the 3 problems. The higher the total score was,the higher a player ranked (the smaller the rank number). If two players gotthe same total score, the one with the smaller ID number got a higher rank.We've known for each problem, how much score each player might get if he didn'tsolve totally wrong (if solved totally wrong, the player got zero in theproblem). However, we don’t know whether a player did get score in a problem.For a predicted final rank, you need to judge if the rank is possible.

Input

Input contains several cases. For each case, the first line is an integer n, (n <= 16384) to indicate the number ofplayers, followed by n lines, the ith of which contains three real numbers a,b, c (0<=a, b, c < 1000. a, b and c have 2 decimal places at most.) torespectively indicate the score of each problem Player i might get if he didn’tsolve totally wrong. Another line containing n integers follows to indicate theplayer ID number in the order from rank 1st to rank nth .

The last caseis followed by a line containing only a zero.

Output

No solution" (quotes for clarity).

Sample Input

3

100 200 300

100 200 300

100 200 300

1 2 3

3

100 200 300

100 200 300

100 200 300

3 2 1

0

Sample Output

Case 1: 600.00

Case 2: 400.00


这道题的来源是:ACM Beijing 2006-E

自己写了代码,提交以后AC了,代码如下:

#include <stdio.h>
#include <stdlib.h>

#define PROBLEM_NUM 3

int main ()
{
	int n = 0; // number of players
	float** grades = NULL; // possible grades if not totally wrong
	float results[1000];
	int* rank = NULL; // predicted rankings
	float grade = 0, temp = 0, temp1 = 0;
	int m = 0; // case counter: case m
	int i = 0, j = 0, k = 0; // loop counter

	scanf("%d", &n);
	while (n) {
		rank = (int*)malloc(sizeof(int) * n);
		grades = (float**)malloc(sizeof(float*) * n);
		for (i = 0; i < n; i++)
			grades[i] = (float*)malloc(sizeof(float) * PROBLEM_NUM);

		// get input
		for (i = 0; i < n; i++)
			for (j = 0; j < PROBLEM_NUM; j++) {
				scanf("%f", &temp);
				getchar(); // get rid of white spaces
				/* Insertion Sort */
				for (k = j; k > 0 && temp < grades[i][k]; k--)
					grades[i][k] = grades[i][k-1];
				grades[i][k] = temp;
			}

		for (i = 0; i < n; getchar(), i++)
			scanf("%d", &rank[i]);

		// judge the rank and find the score
		grade = grades[rank[0]-1][0] + grades[rank[0]-1][1] + grades[rank[0]-1][2];
		temp = 0;
		for (i = 1; i < n; i++) {
			if (rank[i] > rank[i-1]) {
				for (j = 0; j < 8 && temp <= grade; j++) {
					switch (j) { // value of "temp" increases with "j"
					case 0: temp = 0; break;
					case 1: temp = grades[i][0]; break;
					case 2: temp = grades[i][1]; break;
					case 3:
						temp = grades[i][0] + grades[i][1] >= grades[i][2] ? grades[i][2] : grades[i][0] + grades[i][1];
						break;
					case 4:
						temp = grades[i][0] + grades[i][1] <= grades[i][2] ? grades[i][2] : grades[i][0] + grades[i][1];
						break;
					case 5: temp = grades[i][0] + grades[i][2]; break;
					case 6: temp = grades[i][1] + grades[i][2]; break;
					case 7: temp = grades[i][0] + grades[i][1] + grades[i][2]; break;
					default: break;
					}
					temp1 = temp <= grade ? temp : temp1;
				}
			}
			else {
				for (j = 0; j < 8 && temp < grade; j++) {
					switch (j) { // value of "temp" increases with "j"
					case 0: temp = 0; break;
					case 1: temp = grades[i][0]; break;
					case 2: temp = grades[i][1]; break;
					case 3:
						temp = grades[i][0] + grades[i][1] >= grades[i][2] ? grades[i][2] : grades[i][0] + grades[i][1];
						break;
					case 4:
						temp = grades[i][0] + grades[i][1] <= grades[i][2] ? grades[i][2] : grades[i][0] + grades[i][1];
						break;
					case 5: temp = grades[i][0] + grades[i][2]; break;
					case 6: temp = grades[i][1] + grades[i][2]; break;
					case 7: temp = grades[i][0] + grades[i][1] + grades[i][2]; break;
					default: break;
					}
					temp1 = temp < grade ? temp : temp1;
				}
			}
			
			if (j == 1) break;

			grade = temp1;
			temp = temp1 = 0;
		}
		if (i==n && j!= 1)
			results[m] = grade;
		else 
			results[m] = -1;
		m ++;

		// release storage
		for (i = 0; i < n; i++)
			free(grades[i]);
		free(grades);
		free(rank);

		scanf("%d", &n); // player number of next case
	}

	for (i = 0; i < m; i++) {
		if (results[i] != -1)
			printf("Case %d: %.2f\n", i, results[i]);
		else
			printf("Case %d: No solution\n");
	}

	return 0;
}

我的想法是在读取数据的时候进行插入排序,然后判断时利用switch...case...语句从最小值开始尝试所有可能情况。

这个代码有很多地方处理得不太好。

1. 使用了一个定长数组(足够大)results[1000],这个是用来存放结果的。

2. 不能很方便的变化问题个数,当PROBLEM_NUM不为3时,不能直接使用这个代码了;这个主要是受限制于判断部分的switch...case...语句。我采用的处理方法是从最小的可能得分开始尝试,直到最大的可能,有点穷举的味道,我想肯定会有更好的算法。

3. 几乎同样的代码重复出现,就是那两个switch...case...语句那里。

欢迎大家提出想法和意见,让我来学习~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值