/*.关羽过关斩三将,输入四个人的武力值(大于 0 小于 50),若超过界限 需
要重新输入,
关羽的武力值 x,将士武力值为 y,满足(x-y)^2+(x-y)+41 若为素数则关
羽获胜,若关羽三次获胜输出 WIN,若失败则输出 失败输出将领序号(第几关)。
*/
#include<cstdio>
#include<cmath>
bool isprime(int n){
int sqr=(int)sqrt(1.0*n);
for(int i=2;i<=sqr;i++){
if(n%i==0) return false;
}
return true;
}
int main(){
int x,y;
bool flag=true;
scanf("%d",&x);
int i;
for(i=0;i<3;i++){
scanf("%d",&y);
while(y<=0 || y>=50){
printf("please input a num again:\n");
scanf("%d",&y);//不在这个范围内就一直输入
}
int n=(x-y)*(x-y)+(x-y)+41;
if(!isprime(n)){
flag=false;//如果不是素数,则输出
break;
}
}
if(flag) printf("WIN\n");
else{
printf("FAIL in %d\n",&i);
}
return 0;
}
*/
/*输入 N 个员工,每个员工输出 ID 号,上班时间,下班时间,
第一行输出 最早去的员工的 ID 和上班时间
第二行输出 最迟走的员工的 ID 和下班时间
第三行输出 工作最久的员工的 ID 和工作时间
input:
ID100001, 07:00:00 17:00:00
ID100002, 08:00:00 18:00:00
ID100003, 09:00:00 21:00:00
sample out:
OPEN:ID100001, 07:00:00
CLOSE:ID100003, 21:00:00
(…):ID100003, 12:00:00
/
/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1010;
struct staff{
char id[20];
char on[10];//上班时间
char off[10];//下班时间
int total;//总时间
}sta[maxn];
int get_total(char on[],char off[]){
int length=strlen(on);
int hh=0,mm=0,ss=0;
int hh2=0,mm2=0,ss2=0;
int sec1total=0,sec2total=0;
int i=0;
while(i<2){
hh=hh*10+off[i]-'0';
hh2=hh2*10+on[i]-'0';
i++;
}
sec1total+=hh*3600;//下班小时的秒数
sec2total+=hh2*3600;
i++;//将:隔离,i=3
while(i<5){
mm=mm*10+off[i]-'0';
mm2=mm2*10+on[i]-'0';
i++;
}
sec1total+=mm*60;
sec2total+=mm2*60;
while(i<length){
ss=ss*10+off[i]-'0';
ss2=ss2*10+on[i]-'0';
i++;
}
sec1total+=ss;
sec2total+=ss2;
return sec1total-sec2total;
}
bool cmp1(staff a,staff b){
return strcmp(a.on,b.on)<0; //上班时间最小
}
bool cmp2(staff a,staff b){
return strcmp(a.off,b.off)>0; //下班时间最大
}
bool cmp3(staff a,staff b){
return a.total>b.total; //工作时间最大
}
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s %s %s",sta[i].id,sta[i].on,sta[i].off);
sta[i].total=get_total(sta[i].on,sta[i].off);
}
sort(sta,sta+n,cmp1);
printf("OPEN:%s %s\n",sta[0].id,sta[0].on);
sort(sta,sta+n,cmp2);
printf("CLOSE:%s %s\n",sta[0].id,sta[0].off);
sort(sta,sta+n,cmp3);
int hh=sta[0].total/3600;
int mm=sta[0].total%3600/60;
int ss=sta[0].total%60;
printf("LONGEST:%s %02d:%02d:%02d\n",sta[0].id,hh,mm,ss);
return 0;
}
*/
/有一个MN的材料和一个ST的模板,从材料中切除模板,求最大能切除的木板的数量。
sample input:
3 4
a a b a
a b a b
b a b a
2 2
a b
b a
sample out:
3
**此题与上一年的最后一道题有点类似,那道题自己写的是直接用的暴力求解。
百度之后发现有人用DFS来解决,那也可以用BFS
暴力法时间复杂度:需要 (M-S+1)(N-T+1)次的 ST次比较(二维矩阵运算),比如上例,下标从1开始,需要从左上角的
第一个元素开始,到3-2+1=2,第二行,4-2+1=3第三列,这些个元素开始的与模板同样大小的二维矩阵,需要与模板比对
即时间复杂度是O((M-S+1)(N-T+1)ST)=O(x^4),x为max{M-S+1,N-T+1,S,T},这个不太会算
如果用DFS或者BFS,模板中共有ST个顶点,BFS时间复杂度为O(st * st),共需要多少次BFS呢,显然也是(M-S+1)(N-T+1)次
这样一算感觉时间复杂度好像比上一方法还高啊,额…不知道算错没有,欢迎下面指正**
#include<cstdio>
const int maxn=110;
char matrix[maxn][maxn];//材料
char templ[maxn][maxn];//模板
int m,n,s,t;
int ans=0;
void violence(){
for(int i=0;i<m-s+1;i++){
int p=i;
for(int j=0;j<n-t+1;j++){
int q=j;
//s*t次的比较
bool cflag=false;
bool flag=false;//是否和模板相等,true不相等
for(int x=0;x<s;x++){
for(int y=0;y<t;y++){
if(templ[x][y]!=matrix[p][q]) {
flag=true;//表示和模板不相等
cflag=true;
break;
}else{//如果当前元素相等,继续比较
q++;
}
}
p++;
q=j;
if(cflag==true) break;//及时退出循环
}
p=i;
if(flag==false){
ans++;
}
}
}
}
int main(){
scanf("%d%d",&m,&n);
getchar();//吸收换行符
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
scanf("%c",&matrix[i][j]);
getchar();//吸收空格或者换行符
}
}
scanf("%d%d",&s,&t);
getchar();//吸收换行符
for(int i=0;i<s;i++){
for(int j=0;j<t;j++){
scanf("%c",&templ[i][j]);
getchar();//吸收空格或者换行符
}
}
violence();
printf("%d\n",ans);
return 0;
}
//BFS的做法就不做了,懒也可能是自己不会做,自己的思路是:仍然选择下边的两个for循环表示的左上角坐标开始
// for(int i=0;i<m-s+1;i++){ for(int j=0;j<n-t+1;j++){
//然后BFS遍历子模板大小的矩阵,判断是否相等,这里BFS的方向可以只是右边和下边这两个方向,X[i]={1,0},Y[i]={0,1}这是连个方向的增量数组
//然后设置访问条件,边界不访问,入过队的不访问…