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

#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的更多相关文章
随机推荐
- 微信app支付
http://www.bubuko.com/infodetail-1062014.html 要完成手机APP跳转到微信的APP进行微信支付,需要进行如下操作: 1.先去微信的开放平台(http://o ...
- Android Studio 2.3 正式版新功能,你不来看看?!
2017.3.3 Google老大发布了Android Studio 2.3正式版. 在许多2.3beta版本的基础上修复了bug然后推出了正式版.提供了一些新特性,和对部分已有功能的修改完善. Bu ...
- React icon bak
- 如何学好C、C++语言
如何学好C语言 有人在酷壳的留言版上询问下面的问题 keep_walker : 今天晚上我看到这篇文章. http://programmers.stackexchange.com/questions/ ...
- Linux中断的系统调用
早期UNIX系统的一个特性是:如果在进程执行一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用就被中断不再继续执行.该系统调用返回出错,其errno设置为EINTR.这样处理的理由是:因为一个信号 ...
- x电容和Y电容
https://wenku.baidu.com/view/c0a68a6a4a7302768e9939bd.html 根據 IEC 60384-14, 電容器分為 X 電容及 Y 電容 , 1. X ...
- DCM 图片查看
因为要处理一些医学图像,需要把dcm格式的文件转换成jpg格式.本来用Sante DICOM Editor用得挺好的,方便查看dcm文件,但是在转换上每次只能转一张(本人没有找到用该软件批量转格式的方 ...
- 在ubuntu16安装supervisor 并 启动 .net core.
1. 安装supervisor apt-get install supervisor 2.新建supervisor配置文件.使用以下命令在linux 命令行 echo_supervisord_conf ...
- groupby elasticsearch
GET usertag/usertag/_search { "query": { "match": { "tagname": "春 ...
- haproxy文章
http://ximenfeibing.blog.51cto.com/8809812/1663387