主题:[讨论]一道很怪的题
wangzhongqi96
[专家分:40] 发布于 2009-07-12 20:30:00
问题描述
给省队选拔赛命题的时候,周老师手下有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
[color=008000]这道题谁能告诉我如何用动态规划解,并写出状态转移方程和注释[/color][/color][col[size=3]谢谢[/size]
回复列表 (共8个回复)
沙发
tzhlryy [专家分:270] 发布于 2009-08-01 10:34:00
背包问题的变种,把他想成背包问题做,用贪心做
板凳
abcwuhang [专家分:1840] 发布于 2009-08-20 18:35:00
MS不是动规吧,是网络流吧。。~~~
图: ------s-------
| | |
1 2 3
.......
4 5 6
| | |
-------t-------
图画的比较的恶劣~~~~~~凑合吧
解释:123表示人,456表示题目。途中的“……”1到6这6个点之间在图中每一上一下两个点之间连两个点。其中权值1为相应人编相应题目的难度值,权值2为容量(可走次数)。s为源点,t为汇点。从s到123、从456到t权值1(流量)为无限,“……”中的边权值1为,相应人编相应题目的难度值;所有边的权值2为1。所以此题转化为求图中的最大流(对权值2而言)。
hoho~~~此题顺利转型!用一次增广路就OK了。。囍
3 楼
abcwuhang [专家分:1840] 发布于 2009-08-20 18:44:00
晕,我突然觉得自己表达很差~~~要:@@@恶补@@@
4 楼
abcwuhang [专家分:1840] 发布于 2009-08-25 09:35:00
再次归来:
program work;
const maxn=100;
type node1=record
w,f,c:integer
end;
type node2=record
value:integer;
fa:integer;
end;
var a:array[1..maxn+2,1..maxn+2] of node1;
best:array[1..maxn+2] of node2;
n,maxwork,s,t:integer;
procedure init;
var i,j:integer;
begin
readln(n);
fillchar(a,sizeof(a),0);
for i:=1 to n do
for j:=n+1 to 2*n do
begin
read(a[i,j].w);
a[i,j].c:=1;
a[j,i].w:=-a[i,j].w;
end;
s:=2*n+1;
t:=2*n+2;
for i:=1 to n do
begin
a[s,i].c:=1;
a[n+i,t].c:=1;
end;
maxwork:=0;
end;
function find:boolean;
var i,j:integer;
quit:boolean;
begin
fillchar(best,sizeof(best),0);
best[s].value:=1;
repeat
quit:=true;
for i:=1 to 2*n+2 do
if best[i].value>0 then
for j:=1 to 2*n+2 do
if (a[i,j].f<a[i,j].c) then
if best[i].value+a[i,j].w>best[j].value then
begin
best[j].value:=best[i].value+a[i,j].w;
best[j].fa:=i;
quit:=false;
end;
until quit;
if best[t].value>1 then find:=true else find:=false;
end;
procedure add;
var i,j:integer;
begin
i:=t;
while i<>s do
begin
j:=best[i].fa;
inc(a[j,i].f);
a[i,j].f:=-a[j,i].f;
i:=j
end;
inc(maxwork,best[t].value-1);
end;
begin
init;
while find do add;
writeln(maxwork);
end.
另:可能有些变量不同~~~~不过差不多吧
5 楼
1042144576 [专家分:10] 发布于 2009-08-26 17:43:00
嗯,说的没错,这种题一般用最大流做
6 楼
abcwuhang [专家分:1840] 发布于 2009-08-26 17:44:00
MS PKU上有原题。。
7 楼
chip [专家分:80] 发布于 2010-08-07 10:58:00
n较小,应该可以搜索吧!
8 楼
chip [专家分:80] 发布于 2010-08-07 11:21:00
网络流不会,只有搜索解:
program xuanbasai;
var
a:array[1..20,1..20]of longint;
b:array[1..20]of boolean;
i,j,n,max:longint;
procedure find( x,y:longint);
var i:longint;
begin
if x=n+1 then begin if y>max then max:=y; end
else begin
for i:=1 to n do if b[i] then begin
b[i]:=false;
find(x+1,y+a[x,i]);
b[i]:=true;
end;
end;
end;
begin
readln(n);
for i:=1 to n do begin
for j:=1 to n do read(a[i,j]);
readln;
end;
fillchar(b,sizeof(b),true);
for j:=1 to n do begin
b[i]:=false;
find(2,a[1,i]);
b[i]:=true;
end;
writeln(max);
readln;
end.
我来回复