深搜-解决N个命题人,N种不同类型的试题,难度最大的问题

题目:给省队选拔赛命题的时候,周老师手下有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;
		}
	}
}

 

转载于:https://my.oschina.net/u/1403968/blog/3075956

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值