密码盘

来源:互联网 发布:淘宝最火的商品排行榜 编辑:程序博客网 时间:2024/04/29 20:09

Description

【问题描述】

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

例如:假设按钮(1,4)的数值为k,按下它,你获得k分,然后第一行的1会变成0,第四列的0会变成1。

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

这里写图片描述

Input

【输入】

输入文件名为mima.in。

第一行一个正整数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

【输出】

输出文件名为mima.out

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

Sample Input

6

110111

101010

7

5 2 1

3 3 -1

1 4 2

3 5 -2

5 4 3

5 5 -3

6 5 4

Sample Output

6

Data Constraint

Hint

【注释】

样例中除图中灰色的按钮以外,全部都按下。共10个测试数据。

对于第i个测试数据,N=Max{ 3 , Min{ i , 9 }}。

这里写图片描述

分析:用状态压缩DP。设F[I,J,K]为行状态为i,列状态为j,前k个按钮的最大值。可得
f[i,j,k]=max(f[i,j,k-1],f[u,v,k-1]+w[i]) (u,v为转移前的状态)。

代码:

uses math;var f:Array [0..512,0..512,-1..81] of longint; a,b,w:array [1..81] of longint; n,i,j,k,c,x,y,u,v,ans,last:longint; s,t:string;begin readln(n); readln(s); readln(t); last:=1 shl n-1; for i:=1 to n do  x:=x shl 1+ord(s[i])-48; for i:=1 to n do  y:=y shl 1+ord(t[i])-48; readln(c); for i:=1 to c do  readln(a[i],b[i],w[i]); for i:=0 to 512 do  for j:=0 to 512 do   for k:=0 to 81 do    f[i,j,k]:=-maxlongint div 2; f[x,y,0]:=0; for k:=1 to c do  begin   for i:=0 to last do    for j:=0 to last do     begin      u:=i xor (1 shl (n-a[k]));      v:=j xor (1 shl (n-b[k]));      f[i,j,k]:=max(f[i,j,k-1],f[u,v,k-1]+w[k]);     end;  end; ans:=-maxlongint div 3; for i:=0 to last do  ans:=max(f[i,i,c],ans); if ans=-maxlongint div 3 then writeln('I am stupid!')                          else writeln(ans);end.
0 0