【动态规划】LF0YIE'u数(原创题)

在数学界有一类数称之为“LF0YIE'u数”集合(简称为“FIE”),在计算机发展中发挥着不可替代的作用。对于FIE集合并没有严格的数学规定,而是随着某个给定的二进制常数CFIE变化。

给定一个CFIE,如果某个十进制数转化为二进制数后所有含1的位数在CFIE相应位数都是1,则这个数在CFTE常数下属于“FIE”。如CFTE为100111110,那么0就属于“FIE”,2也属于“FIE”,但是1不属于“FIE”。一个合法的“FIE”集合必须满足集合内的0的个数和1的个数的总和分别不能超过CFIE的0的个数和1的个数。对于一个已知区间,把区间中所有属于“FIE”的数组成一个大集合,那么它的子集也是合法的“FIE”。由此可知对于一个CFIE会有很多个与其对应的集合。

在计算机的发展历程中,许多科学家都找出许多符合实际规律的CFIE和它所对应的“FIE”,例如在汇编语言的原始实现中。人们根据0和1的在不同应用中的不同的重要程度,对于每一个CFIE都会给出相应条件下的w0和w1,将某个合法集合中的每一个数转化为二进制数后的0的个数统计并乘以w0即此集合的0价值,将其中的1的个数统计并乘以w1即此集合的1价值,人们根据自己的需要选出实用价值最大的,例如在航天计算中需要0价值最大的集合,而在股市操盘手中需要1价值最大的为实用价值最大的集合。但是0的任何价值都是0.

对于一个给定的CFIE,以及在当前情况下w0和w1,然后给定一个区间[A..B],我们希望找到由此区间中数组成的一个在CFIE下的合法集合,求出当前条件下所需的最大实用价值。

【输入格式】

第一行一个合法二进制数的字符串CFIE,长度为n;

第二行为A,B;

第三行为w0,w1;

第四行为一个由字母组成的字符串s,长度为m,如果s的所有字符对应的ASCII值相加为偶数,则此次操作重点为0价值,反之为1价值。

【输出格式】

一行仅一个数,即最大的实用价值。

【输入样例】

100000111

0 5

1 2

AB

【输出样例】

8

【数据范围】

对于 20% 的数据,n<=10,A<=B<=10。;

对于 100% 的数据,n<=30,A<=B<=maxlongint,B-A<=20000;

对于 100% 的数据,m<=10,w0<=200,w1<=200。

分析

不要被表面现象迷惑,分析发现a,b中的数的个数是一定的,每个数含0和1的个数是确定的,每个数能得到的价值也就随之确定了。可以将给定的0和1的个数看成体积为sum0和sum1的两个背包,每个数都可以看成是一个物品,对于每个数都有取和不取两种状态,这样就转换成了一个二维体积的0/1背包了,压缩一维状态倒序循环即可。

program liukeke;
var
  s1,ss:string;
  w:array[0..1] of longint;
  sum0,sum1,goal,n:longint;
  s:array[0..20000,0..1] of longint;
  f:array[0..50,0..50] of longint;

function max(a,b:longint):longint;
begin
  if a>b then exit(a);
  exit(b);
end;

function change(s:string):longint;
var
  i,j:longint;
begin
  j:=1;
  change:=0;
  for i:=length(s) downto 1 do
  begin
    inc(change,(ord(s[i])-48)*j);
	j:=j*2;
  end;
end;

function find(t,x:longint):longint;
begin
  find:=0;
  while x>0 do
  begin
    if (x mod 2=t)then inc(find);
	x:= x div 2;
  end;
end;


procedure init;
var
  i,sum,tt1,a,b:longint;
  s1,ss:string;
begin
  assign(input,'lfoyie.in'); reset(input);
  assign(output,'lfoyie.out'); rewrite(output);
  readln(s1);
  readln(a,b);
  readln(w[0],w[1]);
  readln(ss);
  for i:=1 to length(s1) do
    if s1[i]='0' then inc(sum0)
                 else inc(sum1);
  tt1:=change(s1);
  n:=0;
  for i:=a to b do
    if tt1 and i=i then
    begin
      inc(n);
	  s[n,0]:=find(0,i);
	  s[n,1]:=find(1,i);
    end;
  sum:=0;
  for i:=1 to length(ss) do
    inc(sum,ord(ss[i]));
  if odd(sum) then goal:=1
              else goal:=0;
end;

procedure dp;
var
  i,j,k:longint;
begin
  for i:=1 to n do
    for j:=sum0 downto s[i,0] do
	  for k:=sum1 downto s[i,1] do
	    f[j,k]:=max(f[j,k],f[j-s[i,0],k-s[i,1]]+w[goal]*s[i,goal]);
end;

procedure outit;
begin
  writeln(f[sum0,sum1]);
  close(input); close(output);
end;

begin
  init;
  dp;
  outit;
end.

反思

背包问题,有些时候背包中的物品是抽象的,所以要将背包,物品的重要元素抽象出来。其本质就是之和当前决策的是否选取有关。

posted @ 2011-06-16 14:57  liukee  阅读(309)  评论(0编辑  收藏  举报