csdn编程挑战 比赛分数

来源:互联网 发布:淘宝秒杀自动刷新 编辑:程序博客网 时间:2024/04/28 20:35

最近看到csdn上的这个题目,题目描述如下:

n个人打乒乓球,每两个人都比赛一场,输者不得分,赢者得1分,最终记录n
个人的得分。但是记录有些缺失,即有些人的得分不见了,你能计算有多少种可能的得分?
矗?输入格式: 多组数据,每组数据两行,第一行是一个正整数n,表示比赛的人数,1 
<= N <=40。 第二行是N个空格分隔的整数,每个整数在-1到(N-1)之间,-1
表示这个人的分数缺失了,非负数表示得分。 输出格式: 
每组数据一行,表示满足条件的得分结果,因为结果比较大,输出对1000000007
取余数的结果。 
挑战规则: 
输入样例 3   -1 -1 2   3   -1 -1 -1   4   0 1 2 3   2   1 1   输出样例: 2 7 
1 0 解释: 第一组 得分可能是{0,1,2} 和 {1,0,2} 第二组 得分可跟是{1,1,1}, {0,1,
2}, {0,2,1}, {1,0,2}, {1,2,0}, {2,0,1}, {2,1,0} 第三组 只能是{0,1,2,3} 
第四组 两个人只能是{1,0} {0,1} 


由于没有怎么做过算法问题,这里想到的第一个问题就是:怎么计算出n个人总共有多少种比赛结果,

显然,每个人的得分应该是在(0,n-1)区间里,并且每两个人只比赛一场,所以还要满足:

1.最多有一个人得分为0

2.最多有一个人得分为n-1

这样就有了思路:

递归依次计算每个人为(0, n-1)时可能的结果数, 相加得到总的结果数。

#include <sys/time.h>#include <unistd.h>#include <stdio.h>//确定数组是否满足限制  int bConf(int arr[], int len){int i ,j;int sum = 0;int tol = len*(len-1)/2;int max = 2*(len-1);int tmp;for (i = 0; i < len; i++){sum += arr[i];for(j = i+1; j < len; j++){tmp = arr[i]+arr[j];if (tmp < 1 || tmp > max)//每两个人的得分和必须在在(1,2*(len-1))区间内 return 0;}}if (sum == tol)return 1;return 0;}int asum(int arr[], int len){int sum = 0;int i;for(i = 0;i < len; i++){sum += arr[i];}return sum;}long func( int arr[], int len, int tsum, int pos){int i = 0;long result = 0;int tmp;int toltal = len*(len-1)/2;int max = 2*(len-1);int arra[40] = {-1};memcpy(arra, arr, len*sizeof(int));if (pos >= len - 1){//最后一个人时 tmp = toltal - asum(arra, len-1);if (arra[pos] == -1){if (tmp >= 0 && tmp < len){//如果分数没有,则它的得分只能是总分数 - 前面所有人得分总和  arra[pos] =  tmp;return bConf(arra, len);}return 0;}else if(tmp == arra[pos]){//如果分数确定,确定这组得分是否满足限制  return bConf(arra, len);}return 0;}if (arra[pos] == -1){for (i = 0; i < len; i++){tmp = tsum + i;if (tmp >= pos && tmp <= (toltal - len + pos + 2)){//从0-pos元素的和必定大于等于pos,因为只能有一个元素为0,其他的都大于0 arra[pos] = i;result += func(arra, len, tsum + i, pos+1);}}}else{tmp = tsum + arra[pos];if (tmp >= pos && tmp <= (toltal - len + pos + 2)){return func(arra, len, tsum+arra[pos], pos+1);}return 0;}return result%1000000007;}int main(){int arr[40] = {-1};struct timeval start, stop;long int tmp;int i, j;int a[3] = {-1, -1, 2};int b[4] = {0,1,2,3};int c[2] = {1,1};printf("%d->%d\n", 2, func(c, 2, 0, 0));printf("%d->%d\n", 3, func(a, 3, 0, 0));printf("%d->%d\n", 4, func(b, 4, 0, 0));for(i = 2;i<41;i++){for(j = 0; j < i; j++){arr[j] = -1;}gettimeofday(&start, NULL);printf("%d->%d\n", i, func(arr, i, 0, 0));gettimeofday(&stop, NULL);tmp = stop.tv_sec - start.tv_sec;tmp = tmp*1000000 + stop.tv_usec - start.tv_usec;printf("consume %f \n", (float)tmp/1000000);}return 0;}
这样虽然能够得到结果,但是效率太低,希望大家一起来交流一下。

第一次写博客,不喜勿喷啊!!!!

                                             
0 0
原创粉丝点击