密码盘 纪中 3067 状压dp

Description

如图是某人设想中的N×N的密码盘,用以显示自己强大的智商以及计算能力。图中每列上面有一个0或1的值,每行左边也有一个0或1的值。密码盘中有最多N*N个按钮,每个按钮有一个数值。按钮按下去之后,你会获得按钮上的分数,然后对应行和对应列的值会改变。

你的任务是,使每列上面的值和每行左边的值一一对应相等(从左到右和从上到下),并且取得最大的积分。当然了初始积分为0。

Input

第一行一个正整数N,表示密码盘的大小。N最大为9。
第二行一个01串,表示从上到下每行左边的N个值。
第三行一个01串,表示从左到右每列上边的N个值。
下一行一个正整数k,表示按钮的数量。1≤k≤N*N。
接下来k行,每行三个整数a、b、c,表示第a行第b列处有一个数值为c的按钮。左上角的格子为第一行第一列。1≤a≤N,1≤b≤N,-100≤C≤100。不会有同一个地方出现两个按钮。

Output

输出一行,包含一个整数,表示所能取得的最大积分。如果不能使得每列上面的值和每行左边的值一一对应相等,输出“I am stupid!”。

分析

谢谢olahiuj的提示
这是一个状压dp,可以把从上到下每行左边的N个值和从左到右每列上边的N个值分别当做一个二进制数,表示状态。

f[l,i,j]=max(f[l1,x,y]+a[l],f[l1,i,j])

i,j表示状态.
x,y表示利用按钮l可以从状态x,y变成i,j.
a[l]表示按钮l的值.

输出时在f[k,i,i]中找到最大的

ps:可以用滚动数组来滚动l.

代码

const
  maxn=1048;

type
  arr=record
    x,y,w:longint;
end;

var
  f:array[0..maxn,0..maxn,0..1] of longint;
  push:array[0..100] of arr;
  n,m,nm:longint;
  x,y:longint;

procedure init;
var
  i,j,k:longint;
  c:char;
begin
  readln(n);
  nm:=0;
  for i:=1 to n do
    begin
      read(c);
      x:=x*2+ord(c)-48;
      nm:=nm*2+1;
    end;
  readln;
  for i:=1 to n do
    begin
      read(c);
      y:=y*2+ord(c)-48;
    end;
  readln;
  readln(m);
  for i:=1 to m do
    with push[i] do
      readln(x,y,w);
  for i:=0 to nm do
    for j:=0 to nm do
      f[i,j,1]:=-maxlongint;
  f[x,y,1]:=0;
end;

function max(x,y:longint):longint;
begin
  if x>y then exit(x)
         else exit(y);
end;

procedure main;
var
  i,j,k,l:longint;
  x1,y1:longint;
  ans:longint;
begin
  l:=1;
  for k:=1 to m do
    begin
      for i:=0 to nm do
        for j:=0 to nm do
          begin
            x1:=i xor (1 shl (n-push[k].y));
            y1:=j xor (1 shl (n-push[k].x));
            if f[x1,y1,l]<>-maxlongint
              then f[i,j,l xor 1]:=max(f[x1,y1,l]+push[k].w,f[i,j,l])
              else f[i,j,l xor 1]:=f[i,j,l];
          end;
      l:=l xor 1;
    end;
  ans:=-maxlongint;
  for i:=1 to nm do
    for j:=i to i do
      if f[i,j,l]>ans then ans:=f[i,j,l];
  if ans<>-maxlongint
    then write(ans)
    else write('ChuTiren is stupid!!!');
end;

begin
  init;
  main;
end.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
开机密码密钥锁 ================== 软件功能: 1-硬开机时须要输入你安装时设置的密码(10位),密码不对开不了机,同时可选择使用USB做为开机密钥。 2-如果安装时插入USB,该将做为开机密钥,开机时显示:Shu Ru Mi Ma:+USB,不插该或插错,即使密码正确,开机后自动关机。 3-如果安装时不插任何USB,将不检查密钥,开机时显示:Shu Ru Mi Ma:只要密码正确就可以开机。 4-安装时修改硬MBR,故最好备份硬分区表到可以启动的USB,同时关闭杀毒软件以防禁止操作。 5-安装本软件的硬分区表加密存放,故用光或其它启动启动也看不见此硬,该硬的数据彻底得到保护,即使挂到其它电脑上也看不见。 6-做为开机密钥的USB没有特殊要求也不写入任何数据,当然如果想用它启动要自行制作USB启动!做好密钥后最好不要再对其格式化。 7-本软件有注册窗口和机器码,但安装后可以无限制使用,不注册明年起只在安装时有限制(7次)重新安装系统或恢复系统备份时此限制取消。 8-为了安全最好在不重要的机器上试验,否则后果自负。 本软件在自己的联想笔记本和技嘉台式机上,WINXP,WIN7,WIN8系统下测试2年正常,其它机器环境下未做普遍试验, 希望试用的朋友做好硬主引导区MBR备份及恢复工具,如果出现开不了机,用USB启动,恢复MBR就可以开机,重新安装后再卸载可以完全清除。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值