题目:给省队选拔赛命题的时候,周老师手下有N个命题人,要命N种不同类型的试题,其中每人命每一类型的试题一题。因为每个命题人对不同题型的掌握程度不同,所以他们编出的试题难度也有不同(这用一个难度数值来表示)。为了尽可能地刁难大家,周老师决定出一张N个题的试卷,每一类型的试题一题,而且所有题的难度值总和最大。
- 输入数据
第一行为N(N <= 20),代表命题人的个数。(40%的数据N<=10)
以后N行,每行N个整数(每个数不超过100),第i行j列的数表示第i个人出的第j种题目的难度大小。
- 输出数据
一行,表示试卷难度的最大值。
- 样例输入
3
50 50 1
10 100 10
100 10 10
- 样例输出
201
分析:命题要求其中每人命每一类型试题一题。其结果是从数据方阵中每行每列中仅且必须选取一个数字,使相加结果为最大值。
原题附录pascal答案经过测试有问题,修改如下:
program sample1_1;
var
a:array[1..20,1..20]of integer;
b:array[1..20]of boolean;
d:array[0..21]of integer;
max,n,i,j:integer;
f:text;
//本题解决方案是深搜,题目关键要求是同一列只选取一个数字
procedure step(x,s:integer);
var
i:integer;
begin
//此处应该是s+d[x]而不是x+1,已更正。x+1时结果为160,显然是错的
if s+d[x]<=max then exit;
if x>n then
if s>max then begin max:=s; exit; end;
for i:=1 to n do
if b[i] then
begin
b[i]:= false;//标记已被选过的题目
step(x+1, s+a[x, i]);
b[i]:= true;//标记该题目未被选择
end;
end;
begin
assign(f, 'C:\Users\Raytine\Desktop\backup\input.in');
reset(f);
readln(f,n);
writeln(n);
for i:=1 to n do
begin
for j:=1 to n do
read(f, a[i, j]);
readln(f);
end;
close(f);
d[n+1]:= 0;
//设置展望值,其目的是计算第x步时,其余(n-x)个数字所能组成的最大值d[x](不考虑同列唯一)
//x步的结果s + d[x] < max时,就没必要继续搜索,
for i:=n downto 1 do
begin
d[i]:=a[i,1];
for j:=2 to n do
if a[i,j]>d[i] then d[i]:=a[i,j];
d[i]:=d[i]+d[i+1];
end;
max:=0;
fillchar(b,sizeof(b),true);
step(1,0);
writeln(max);
end.
c语言代码如下
#include <stdio.h>
int max = 0, n, b[100], a[100][100];;
int main()
{
int tryinput(int k, int res);
char ch;
FILE* fp;
int i, j, res;
char f;
for (i = 0; i < 100; i++)
{
b[i] = true;
}
if ((fp = fopen("list.txt", "r")) == NULL)
{
printf("file open error!");
return 0;
}
fscanf(fp, "%d\n", &n);
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
fscanf(fp, "%d ", &a[i][j]);
}
}
res = 0;
tryinput(0, res);
printf("%d\n", max);
}
int tryinput(int k, int res)
{
int i;
if (max < res)
{
max = res;
}
if (k >= n )
{
return res;
}
for (i = 0; i < n; i++)
{
if (b[i])
{
b[i] = false;
tryinput(k+1, res + a[k][i]);
b[i] = true;
}
}
}