标签归档:最佳课题选择

最佳课题选择

问题描述
  Matrix67要在下个月交给老师n篇论文,论文的内容可以从m个课题中选择。由于课题数有限,Matrix67不得不重复选择一些课题。完成不同课题的论文所花的时间不同。具体地说,对于某个课题i,若Matrix67计划一共写x篇论文,则完成该课题的论文总共需要花费Ai*x^Bi个单位时间(系数Ai和指数Bi均为正整数)。给定与每一个课题相对应的Ai和Bi的值,请帮助Matrix67计算出如何选择论文的课题使得他可以花费最少的时间完成这n篇论文。

输入格式 Input Format
  第一行有两个用空格隔开的正整数n和m,分别代表需要完成的论文数和可供选择的课题数。
  以下m行每行有两个用空格隔开的正整数。其中,第i行的两个数分别代表与第i个课题相对应的时间系数Ai和指数Bi。
  对于30%的数据,n<=10,m<=5;   对于100%的数据,n<=200,m<=20,Ai<=100,Bi<=5。 输出格式 Output Format
  输出完成n篇论文所需要耗费的最少时间。

样例输入 Sample Input
10 3
2 1
1 2
2 1

样例输出 Sample Output
19

注释 Hint
样例说明:
  4篇论文选择课题一,5篇论文选择课题三,剩下一篇论文选择课题二,总耗时为2*4^1+1*1^2+2*5^1=8+1+10=19。可以证明,不存在更优的方案使耗时小于19。

算法分析
f[i,j]表示前i个课题选j篇论文所花的最少时间
f[i,j]=max{f[i-1,j-k]+cal(a[i],k,b[i])}
一定要记得:
0 <= k <= j cal()是计算函数 【代码】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <string.h>
__int64 min(__int64 a, __int64 b)
{
       return a<b?a:b;
}
__int64 cal(int a, int x, int b)
{
       __int64 temp = 1;
       int i;
       for (i = 1; i <= b; i++)
              temp = temp * x;
       return temp * a;
}
 
int main()
{
       __int64 f[21][201];       //f[i,j]表示前i个课题选j篇论文所花的最少时间
       int a[21], b[21];
       int n, i, j, m, k;
       scanf("%d %d", &n, &m);
       for (i = 1; i <= m; i++)
              scanf("%d %d", &a[i], &b[i]);
 
       memset(f, 0, sizeof(f));
 
       for (i = 1; i <= n; i++)
       {
              f[1][i] = cal(a[1], i, b[1]);
       }
 
       for (i = 2; i <= m; i++)
       {
              for (j = 1; j <= n; j++)
              {
                     f[i][j] = f[i - 1][j];
                     for (k = 0; k <= j; k++)
                            f[i][j] = min(f[i][j], f[i - 1][j - k] + cal(a[i], k, b[i]));
              }
       }
 
       printf("%I64d\n", f[m][n]);
       return 0;
}