这是一个类似密码锁的东西。
一开始的时候密码设置在第一列,我们可以通过拨动来改变每一行的密码。
合法的密码必须满足三个条件:
①至少有一个数字。
②至少有一个小写字母。
③至少有一个特殊字符(*&#)
问最少拨动多少下就能得到合法的密码。
思路:
因为只要满足这三个条件就能算是一个合法密码,那么也就是说,我们只要枚举三行使得这三行一个拨动到数字,一个拨动到小写字母,一个拨动到特殊字符即可。
这三行需要维护一个最小拨动次数。
那么我们的任务就是O(n^3)枚举这三行,接下来O(M)来维护当前情况的最小拨动次数即可
对于可行解,维护最小输出。
总时间复杂度O(n^3m);
Ac代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
char a[500][800];
int b[50*50*50];
int c[50*50*50];
int d[50*50*50];
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
{
scanf("%s",a[i]);
}
int output=0x3f3f3f3f;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=1;k<=n;k++)
{
if(i==j||j==k||i==k)continue;
int sum1=0x3f3f3f3f;
for(int z=0;z<m;z++)
{
if(a[i][z]>='0'&&a[i][z]<='9')
{
sum1=min(sum1,min(z,m-z));
}
}
int sum2=0x3f3f3f3f;
for(int z=0;z<m;z++)
{
if(a[j][z]>='a'&&a[j][z]<='z')
{
sum2=min(sum2,min(z,m-z));
}
}
int sum3=0x3f3f3f3f;
for(int z=0;z<m;z++)
{
if(a[k][z]=='*'||a[k][z]=='#'||a[k][z]=='&')
{
sum3=min(sum3,min(z,m-z));
}
}
if(sum1==0x3f3f3f3f||sum2==0x3f3f3f3f||sum3==0x3f3f3f3f)continue;
output=min(output,sum1+sum2+sum3);
}
}
}
printf("%d\n",output);
}
}