http://acm.fzu.edu.cn/problem.php?pid=2158

在密室逃脱游戏中,大家被困在一个密室中,为了逃出密室,需要找到正确的数字密码,于是大家分头行动,分别找到了密码的子序列,而后大家将得到的线索集中整理分析,大家想知道密码最少是多少位。第一行输入一个整数T,表示数据组数。接下来T组数据,对于每组数据,第一行输入一个整数n (1<=n<=7),表示有n个人,接下来第2到n+1行每行输入一串数字,分别表示第i个人得到的密码子序列(长度<=6)。

1
3
123
14
21
5
比赛的时候是3秒,以前在做搜索的遇到过类似的题目,我是用A*过的.....在这里被卡住了
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int len[8],n,flag,p,dp[8][10];
char s[8][8]; int deal()
{
int maxn=0;
for(int i=0;i<n;i++)
maxn=max(maxn,len[i]);
return maxn;
}
int deal1()
{
int sum=0;
for(int j=0;j<=9;j++)
{
int maxn=0;
for(int i=0;i<n;i++)
{
maxn=max(maxn,dp[i][j]);
}
sum+=maxn;
}
return sum;
}
void dfs(int step)
{
if(flag==1)
return;
int x=deal();
int y=deal1();
if(x==0)
{
flag=1;
return;
}
if(step+x>p||step+y>p)
return;
for(int i=0;i<n;i++)
{
if(len[i]==0) continue;
int f[10],cnt=0;
int tmp=len[i]-1;
int xx=s[i][tmp]-'0';
for(int j=0;j<n;j++)
{
if(len[j]==0) continue;
int tmp1=len[j]-1;
if(s[i][tmp]==s[j][tmp1])
{
len[j]--;
f[cnt++]=j;
dp[j][xx]--;
}
}
if(cnt)
{
dfs(step+1);
for(int i=0;i<cnt;i++)
{
int tmp2=f[i];
len[tmp2]++;
dp[tmp2][xx]++;
}
}
}
}
int main()
{
int text;
scanf("%d",&text);
while(text--)
{
scanf("%d",&n);
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
scanf("%s",s[i]);
len[i]=strlen(s[i]);
for(int j=0;j<len[i];j++)
{
int tmp=s[i][j]-'0';
dp[i][tmp]++;
}
}
p=flag=0;
p=max(deal1(),deal());
while(1)
{
dfs(0);
if(flag==1)
break;
p++;
}
printf("%d\n",p);
}
return 0;
}

  比赛完了,挂出来是1s的时候,在朋友的提醒下,用dp过的,简单的说下思路:

我开了7维dp,每一维分别对应这一维的字符串还有多少个字母没有匹配完的情况下所需要的最少字符个数。

我采取的是从n个字符串的最后开始往前面匹配的,每次找一个字符,看它是否与其它几个字符串相应位置上的字符相等,相等就-1,我所采取的方法是记忆化搜索,感觉这样容易把思路提现出来.......下面是代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define inf (1<<28)
int dp[7][7][7][7][7][7][7],n,t[8];
char s[8][10]; int dfs(int a,int b,int c,int d,int e,int f,int g)
{
if(a==0&&b==0&&c==0&&d==0&&e==0&&f==0&&g==0)
return 0;
if(dp[a][b][c][d][e][f][g]) return dp[a][b][c][d][e][f][g];
//int h[7];
/*h[0]=a;
h[1]=b;
h[2]=c;
h[3]=d;
h[4]=e;
h[5]=f;*/
int minx=inf;
//if(a>0)
for(int j=0;j<n;j++)
{
if(t[j]==0) continue;
int f[7],cnt=0;
int tmp=t[j];
for(int i=0;i<n;i++)
{
if(t[i]==0) continue;
int tmp1=t[i];
if(s[i][tmp1-1]==s[j][tmp-1])
{
//if(a==3&&b==2&&c==2)
//printf("%c %c %d %d\n",s[i][t[i]-1],s[j][t[j]-1],i,j);
f[cnt++]=i;
t[i]--;
}
}
//if(a==3&&b==2&&c==2)
//printf("%d %d %d\n",t[0],t[1],t[2]);
//if(t[0]==3&&t[1]==1&&t[2]==1)
//printf("%c\n",s[j][t[j]-1]);
if(cnt)
{
int p=1+dfs(t[0],t[1],t[2],t[3],t[4],t[5],t[6]);
minx=min(minx,p);
//if(a==2&&b==1&&c==2)
//printf("%d %d %d %d %d\n",t[0],t[1],t[2],minx,p-1);
for(int i=0;i<cnt;i++)
{
int x=f[i];
t[x]++;
}
}
}
dp[a][b][c][d][e][f][g]=minx;
//printf("%d %d %d %d\n",a,b,c,minx);
return minx;
}
int main()
{
int text;
scanf("%d",&text);
while(text--)
{
scanf("%d",&n);
memset(dp,0,sizeof(dp));
memset(t,0,sizeof(t));
for(int i=0;i<n;i++)
{
scanf("%s",s[i]);
t[i]=strlen(s[i]);
//printf("%d\n",t[i]);
}
printf("%d\n",dfs(t[0],t[1],t[2],t[3],t[4],t[5],t[6]));
//for(int i=0;i<n;i++)
//printf("%d\t",t[i]);
}
return 0;
}

  

 

fzu2158的更多相关文章

随机推荐

  1. 运维自动化之Cobbler系统安装使用详解[good]

    一.简介 Cobbler是一个快速网络安装linux的服务,而且在经过调整也可以支持网络安装windows.该工具使用python开发,小巧轻便(才15k行python代码),使用简单的命令即可完成P ...

  2. IIS7虚拟目录出现HTTP错误500.19(由于权限不足而无法读取配置文件)的解决方案

    今天在window7上配置asp.net网站,但是访问总是提示 错误摘要HTTP 错误 500.19 - Internal Server Error无法访问请求的页面,因为该页的相关配置数据无效.详细 ...

  3. SQL Server 2008中SQL之WaitFor

    SQL Server 2008中SQL应用系列--目录索引 在SQL Server 2005以上版本中,在一个增强的WaitFor命令,其作用可以和一个job相当.但使用更加简捷. 看MSDN: ht ...

  4. php mysql procedure获取多个结果集

    protected function getRs($id) { $db = new mysqli(C("DB_HOST"), C("DB_USER"), C(& ...

  5. Oracle 12C -- 手动创建CDB

    1.指定oracle_sid $ export ORACLE_SID=db12 2.指定环境变量 比如ORACLE_BASE.ORACLE_HOME.PATH(要包含$ORACLE_HOME/bin) ...

  6. MySQL执行mysql_install_db初始化

    # ./mysql_install_db \ > --defaults-file=/etc/my.cnf \ > --basedir=/data/mysql \ > --datadi ...

  7. 64位平台C/C++开发注意事项

    在http://www.viva64.com/en/l/上例出了28个在64位平台上使用C/C++开发的注意事项,对于进入64位时代的程序员应该去看看这28个事项,这些英文读物对于有C/C++功底的朋 ...

  8. 实现一个简单的android开关

    近期在学习android中的graphics中绘图系列.依照大神思路.找葫芦画瓢实现了一个开关.如图下: 记录一下实现方式: 1.画背景 上图形状.分成两个半圆与一个矩形,那么代码能够写成: priv ...

  9. 基于Docker搭建LNMP环境(转)

    关于什么是docker,建议大家先上网查查有关的用法.如果您不了解,在这篇文章中,您可以简单的理解为他是一个轻量级的虚拟机. 一.docker安装mysql 首先,我们从仓库拉取一个MySql的镜像 ...

  10. 安装Flume的时候出现File Channel transaction capacity cannot be greater than the capacity of the channel capacity -解决方案 摘自网络

    部署flume集群时,在启动collector服务器没报错,启动agent服务器报错: File Channel transaction capacity cannot be greater than ...