搜索TwT

今天化身WA队金牌剪枝园丁疯狂TLE

Day1T1:

Day1T1http://118.31.67.228/problem.php?cid=1020&pid=0http://118.31.67.228/problem.php?cid=1020&pid=0

样例输入:

5 3

样例输出 :

  1  2  31  2  41  2  51  3  41  3  51  4  52  3  42  3  52  4  53  4  5

题解:

三年前可以写出来的题,不会现在写不出来吧,写不来该挨打

#include<cstdio>using namespace std;int n,r;
int now[30];
bool vis[30];inline void dfs(int fath,int depth)
{if(depth==r+1){for(int i=1;i<depth;i++)printf("%3d",now[i]);putchar('\n');return ;}for(int i=fath+1;i<=n;i++){if(vis[i]==0){vis[i]=1;now[depth]=i;dfs(i,depth+1);vis[i]=0;now[depth]=0;}}
}int main(void)
{scanf("%d%d",&n,&r);dfs(0,1);
}

Day1T2:

Day1T2http://118.31.67.228/problem.php?cid=1020&pid=1

样例输入:

4 6
a t c i s w

样例输出 :

acis
acit
aciw
acst
acsw
actw
aist
aisw
aitw
astw
cist
cisw
citw
istw

题解:

正解说是要:

【知识讲解】

深度优先搜索中的剪枝优化:

在深度优先搜索的过程中,如果发现以当前状态往下搜索,不可能得到解或者最优解,那么就应该及时“后退”,避免搜索当前结点(状态)下面的“子搜索树”,以减少搜索时间,提高搜索效率。这种思想称为搜索“剪枝”。这跟走迷宫时提前判断出“死胡同”,不走冤枉路一个意思。

【问题分析】

设len表示读人(要生成)的串长,num表示字符的总个数。因为所有的密码都要按字典序输出,所以对读入的所有字符a[i]按升序排列。为了处理方便,再设b[i]表示数组a中位置i及之后还有几个元音。

采用深度优先搜索,设dfs(x,y,n1 ,n2,s)表示搜到第x个字符,即将生成的字符串长度为y,至少还要nl个元音和n2个辅音,生成的字符串为s,则可以得到以下代码:

void dfs(int x,int y,int n1,int n2, string s){

if(y == len+1){

输出s;

计数器加1,如果等于25000就中止程序;

}

else if(a[i] 是元音) dfs(x+1,y+1,n1-1,n2,s+a[x]);

else dfs(x+1,y+1,n1,n2-1,s+a[x]);

}

直接调用dfs(1,1,1,2,"")即可。但是,运行程序发现超时严重。下面考虑对递归代码(阴影部分)进行适当的剪枝优化。

(1)如果接下来的字母全用上但长度也不够,则剪枝。

(2)如果接下来没有元音且之前没有用过元音,则剪枝。

(3)如果接下来的辅音全取完再加上之前取的辅音也不够2个,则剪枝。

但是!完全不用

因为只让我们输出25000个我们只需要枚举出所有排列,输出符合两个辅音一个元音的情况,到25000个的时候直接终止

#include<cstdio>
#include<iostream>
#include<algorithm>using namespace std;int n,r;
char val[30];
char now[30];
bool vis[30];
int k1,k2;
int cnt;inline void dfs(int fath,int depth)
{if(cnt>=25000)return;if(depth==r+1){k1=0;k2=0;for(int i=1;i<depth;i++){if( now[i]=='a'||now[i]=='e'||now[i]=='i'||now[i]=='o'||now[i]=='u')k1++;else k2++;}if(k1<1 || k2<2)return;for(int i=1;i<depth;i++)putchar(now[i]);putchar('\n');cnt++;return ;}for(int i=fath+1;i<=n;i++){if(vis[i]==0){vis[i]=1;now[depth]=val[i];dfs(i,depth+1);vis[i]=0;now[depth]=' ';}}
}int main(void)
{scanf("%d%d",&r,&n);for(int i=1;i<=n;i++)cin>>val[i];sort(val+1,val+1+n);cnt=0;dfs(0,1);
}

Day1T3:

Day1T3http://118.31.67.228/problem.php?cid=1020&pid=2

样例输入:

5 10
2 2 6 5 4

样例输出 :

2 2 6 

题解:

其实最搞人的不是数据太大被卡,最搞人最难受的是题面告诉你数据巨大,事实上不优化一次过,加了优化全部TLE(OIER崩溃的瞬间

对于这种问题,当n比较小的时候用搜索合适,当c比较小的时候用背包比较合适,但是背包想要输出方案相当麻烦。但是要是数据真的像题面那样ex的话,对于现在的我无法解决。

2、3、4行都是加了排序后搜索的,超时,1行是啥也不加的暴力中的暴力哭了QAQ

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>using namespace std;int n,pur;
int val[100000];
int now[30000];
int sum[30000];
bool vis[30000];template <typename T>inline void in(T &x)
{T ch=getchar(),xx=0,fw=1;while(!isdigit(ch)){if(ch=='-')fw=-1;ch=getchar();}while(isdigit(ch)){xx=(xx<<1)+(xx<<3)+ch-'0';ch=getchar();}x=xx*fw;
}template <typename T>inline void prt(T x)
{if(x>9)prt(x/10);putchar(x%10+'0');
}inline void dfs(int fath,int depth,int state)
{if(vis[0]==1)return;if(sum[n]-sum[fath-1]<pur-state)return;if(state==pur){for(register int i=1;i<depth;i++)prt(now[i]),putchar(' ');putchar('\n');vis[0]=1;return;}if(depth==n+1)return;for(register int i=1;i<=n;i++){if(vis[i]==0 && state+val[i]<=pur){vis[i]=1;now[depth]=val[i];dfs(i,depth+1,state+val[i]);vis[i]=0;now[depth]=0;}}
}inline bool tmp(int xx,int yy){return xx>yy;}int main(void)
{in(n);in(pur);for(register int i=1;i<=n;i++)in(val[i]),sum[i]=sum[i-1]+val[i];//sort(val+1,val+1+n,tmp);dfs(1,1,0);if(vis[0]==0)printf("No Solution!");return 0;
}

Day1T5:

Day1T5http://118.31.67.228/problem.php?cid=1020&pid=4

样例输入:

.2738..1..1...6735.......293.5692.8...........6.1745.364.......9518...7..8..6534.
......52..8.4......3...9...5.1...6..2..7........3.....6...1..........7.4.......3.

样例输出 :

527389416819426735436751829375692184194538267268174593643217958951843672782965341
416837529982465371735129468571298643293746185864351297647913852359682714128574936

题解:

和这个该死的蛋疼的题斗智斗勇了一下午,它终于还是低在了我和巨人的脚下

不bb了,这道题单纯的判断横竖正方形是肯定不行的,这时,我们强大的状态压缩登场了,这道题只有9个数,所以一个511的数字就可以存下所有可能的状态了,比如101011000这个数就表示1、2、3、6、8这五个数字已经被填过了,那我们就把每一行、每一列、每一个正方形的状态压缩出来,然后对于一个位置,将三数&起来然后取lowbit就是这个空可以填的数

你以为这样就完了吗?NoNoNo

这样以来只是优化了判断能不能填,我们还有优化每次填那里

第一次我想的是每一层dfs枚举所有位置看能填什么这样以来,成功的样例直接TLE;

然后我更换了我的策略:dfs存储当前所在位置,然后依次从左上往右下角枚举,这样相比前一种方法有了效率质的飞跃(不会去看已经填了的空,并且保证是枚举完了一行才去枚举下一行,保证有序性),可以秒过样例了,但是OJ上还是全TLE

然后进一步优化,不再是呆板的从左上到右下枚举,而是每次枚举一个空,这个空是当前情况能填入数最少的一个,我加入了MMin函数、并且预处理出每个状态里面有多少个1:例如

还有一个剪枝:就是在求最小的可填数的位置时,如果出现一个空的可填数是0,表明当前状态最终是不能达到正解的,直接return(这个优化了很多)

inline pair<int,int> MMin()
{int minn=10000;pair<int,int> ret=make_pair(0,0);for(int i=1;i<=9;i++){for(int j=1;j<=9;j++){if(ch[i][j]!='.')continue;int now=he[i]&shu[j]&sqr[z[i][j]];if(now==0)return make_pair(-1,-1);if(minn>nu[now]){minn=nu[now];ret.first=i;ret.second=j;}}}return ret;
}

值得一提的是方案三A了这道题,但是用第二种方案和第三种方案分别跑强度低的数据和强度高的数据,对于强度低的,第三种比第二种快,而强度高的,第二种比第三种快(有之前TitanV和RTX2080那味了

#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>using namespace std;char ch[20][20];
int he[10],shu[10],sqr[10];
int nu[2048];
int sum;
bool flag;inline int lowbit(int x) {return x&(-x);
}int z[10][10]={{0,0,0,0,0,0,0,0,0,0},{0,1,1,1,2,2,2,3,3,3},{0,1,1,1,2,2,2,3,3,3},{0,1,1,1,2,2,2,3,3,3},{0,4,4,4,5,5,5,6,6,6},{0,4,4,4,5,5,5,6,6,6},{0,4,4,4,5,5,5,6,6,6},{0,7,7,7,8,8,8,9,9,9},{0,7,7,7,8,8,8,9,9,9},{0,7,7,7,8,8,8,9,9,9}};inline pair<int,int> MMin()
{int minn=10000;pair<int,int> ret=make_pair(0,0);for(int i=1;i<=9;i++){for(int j=1;j<=9;j++){if(ch[i][j]!='.')continue;int now=he[i]&shu[j]&sqr[z[i][j]];if(now==0)return make_pair(-1,-1);if(minn>nu[now]){minn=nu[now];ret.first=i;ret.second=j;}}}return ret;
}inline bool dfs(int remain,int xx,int yy) {if(xx==-1)return 0;int now=he[xx]&shu[yy]&sqr[z[xx][yy]];if(now==0)return 0;for(int k=now; k; k-=lowbit(k)) {int num=lowbit(k);num=log(num)/log(2);ch[xx][yy]=(char)(num+'0'+1);he[xx]-=(1<<(num));shu[yy]-=(1<<(num));sqr[z[xx][yy]]-=(1<<(num));pair<int,int>d=MMin();if(d.first==-1){ch[xx][yy]='.';he[xx]+=(1<<(num));shu[yy]+=(1<<(num));sqr[z[xx][yy]]+=(1<<(num));continue;}if(d.first==0) return true;if(dfs(remain-1,d.first,d.second)) return true;ch[xx][yy]='.';he[xx]+=(1<<(num));shu[yy]+=(1<<(num));sqr[z[xx][yy]]+=(1<<(num));}return 0;
}inline void prework()
{memset(nu,0,sizeof(nu));for(int i=1;i<=511;i++){int now=i;while(now){nu[i]++;now-=lowbit(now);}
}
}int main(void) {prework();while(1) {memset(he,0,sizeof(he));memset(shu,0,sizeof(shu));memset(sqr,0,sizeof(sqr));for(int i=1; i<=9; i++) {for(int j=1; j<=9; j++) {cin>>ch[i][j];if(ch[i][j]=='e') {return 0;}}//scanf("%c",ch[i][j]);}sum=0;flag=0;for(int i=1; i<=9; i++) {for(int j=1; j<=9; j++) {if(ch[i][j]!='.') {he[i]|=1<<(ch[i][j]-'0'-1);shu[j]|=1<<(ch[i][j]-'0'-1);sqr[z[i][j]]|=1<<(ch[i][j]-'0'-1);} else sum++;}}for(int i=1; i<=9; i++) {he[i]=he[i]^511;shu[i]=shu[i]^511;sqr[i]=sqr[i]^511;}dfs(sum,MMin().first,MMin().second);for(int y=1; y<=9; y++)for(int t=1; t<=9; t++)putchar(ch[y][t]);putchar('\n');}
}

----------------------------------我是分隔线-------------------------------------

Day2T1:

Day2T1http://118.31.67.228/problem.php?cid=1024&pid=0

样例输入:

3 3
1 3 1 2
1 2 1 2
2 3 1 2

样例输出 :

2

题解:

这道题刚刚拿到的时候,有点不知所措,但是仔细分析,我们不能把A、B的行动放在一起看我们要将其分成两个部分,单独处理出A、B可能到达终点的时间。判断有没有相等的情况就可以了。

注意:判断有没有相同的值时要用map,不然TLE警告

Day2T2:

Day2T2http://118.31.67.228/problem.php?cid=1024&pid=1

样例输入:

3 4
OXXO
XXOO
XOOO
3 2 2 4
3 3 1 1
0 0 0 0

样例输出 :

1
Impossible!

题解:

第一次看到这道题想的是如何快速的处理出地图上能攻击到敌人的位置,于是就被这里卡住了,考下来才听说,直接暴力处理出能a到的地方就可以了(当场emo,所以啊先把暴力写出来再去想优化吧

除了预处理写起来有点烦人以外,其他都还好

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>using namespace std;int n,m;
int ans;
int ko[300][300];
char ma[300][300];
int col[300][300];
int mov[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
int x1,yy1,x2,y2;
bool flag;
int atck[300][300];
int dis[300][300];inline bool kd(int x,int y)
{return (x>=1 && x<=n && y>=1 && y<=m);
}queue< pair<int,int> >q;inline void BFS()
{memset(dis,0,sizeof(dis));q.push(make_pair(x2,y2));dis[x2][y2]=0;while(!q.empty()){pair<int,int>now=q.front();q.pop();if(atck[now.first][now.second]==1){ans=dis[now.first][now.second];return ;}int x=now.first,y=now.second;for(int i=0;i<4;i++){if(  kd(x+mov[i][0],y+mov[i][1]) && ma[x+mov[i][0]][y+mov[i][1]]=='O' &&dis[x+mov[i][0]][y+mov[i][1]]==0){dis[x+mov[i][0]][y+mov[i][1]]=dis[x][y]+1;q.push(make_pair(x+mov[i][0],y+mov[i][1]));}}}
}inline void dfs_2(int x,int y)
{col[x][y]=1;for(int i=0;i<4;i++){if(kd(x+mov[i][0],y+mov[i][1]) && ma[x+mov[i][0]][y+mov[i][1]]=='O' && col[x+mov[i][0]][y+mov[i][1]]==0){col[x+mov[i][0]][y+mov[i][1]]=1;dfs_2(x+mov[i][0],y+mov[i][1]);}}
}inline void prework(int x,int y)
{memset(atck,0,sizeof(atck));for(int i=x;i<=n;i++){if(ma[i][y]=='X')break;atck[i][y]=1;}for(int i=x;i>=1;i--){if(ma[i][y]=='X')break;atck[i][y]=1;}for(int i=y;i<=m;i++){if(ma[x][i]=='X')break;atck[x][i]=1;}for(int i=y;i>=1;i--){if(ma[x][i]=='X')break;atck[x][i]=1;}for(int i=1;i<=min(n-x,m-y);i++){if(ma[x+i][y+i]=='X')break;atck[x+i][y+i]=1;}for(int i=1;i<=min(n-x,y);i++){if(ma[x+i][y-i]=='X')break;atck[x+i][y-i]=1;}for(int i=1;i<=min(x,m-y);i++){if(ma[x-i][y+i]=='X')break;atck[x-i][y+i]=1;}for(int i=1;i<=min(x,y);i++){if(ma[x-i][y-i]=='X')break;atck[x-i][y-i]=1;}
}inline void clr()
{queue<pair<int ,int> >emp;swap(emp,q);
}int main(void)
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>ma[i][j];}}scanf("%d%d%d%d",&x1,&yy1,&x2,&y2);while(x1+x2+yy1+y2){ans=-1;clr();prework(x1,yy1);BFS();if(ans==-1)printf("Impossible!\n");else printf("%d\n",ans);scanf("%d%d%d%d",&x1,&yy1,&x2,&y2);}
}
/*
3 4
OXXO
XXOO
XOOO
3 2 2 4
3 3 1 1
0 0 0 0
*/

Day2T3:

Day2T3http://118.31.67.228/problem.php?cid=1024&pid=2

样例输入:

4
aacc

样例输出 :

aacc
acac
acca
caac
caca
ccaa
6

题解:

今天学到了一个高级东西,next_permutation(a+1,a+n+1,tmp),它可以得到任意长度的全排列,并且不会有重复,当所有排列都输出了它会自己回到原来的序列,所以当得到的序列再一次等于自身时,就结束。

#include<cstdio>
#include<iostream>
#include<map>
#include<cstring>
#include<string>
#include<algorithm>using namespace std;int n;
char ch[1000];
map<string , bool>Hash;
bool vis[1000];
int cnt;int main(void)
{scanf("%d",&n);//cin.tie(0);cout.tie(0);cin>>ch;sort(ch,ch+n);while(1){Hash[ch]=true;cnt++;for(int i=0;i<n;i++)printf("%c",ch[i]);printf("\n");next_permutation(ch,ch+n);if(Hash[ch]!=0)break;}printf("%d",cnt);
}

Day2T4:

Day2T4http://118.31.67.228/problem.php?cid=1024&pid=3

样例输入:

4 5
.....
.X...
...*X
X.X..
3
NORTH
WEST
SOUTH

样例输出 :

.....
*X*..
*.*.X
X.X..

题解:

这道题不用dfs,对于每一个操作,我们只关注每一个操作,把当前操作的所有状态都画在图上,下一个操作对这些操作再次拓展,这样历来更加高效稳定,注意一次操作不要把新鲜更新出来的状态也操作了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>using namespace std;int n,m;
int k;
char ma[300][300];
char s[200];
int st_x,st_y;int main(void)
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>ma[i][j];if(ma[i][j]=='*')st_x=i,st_y=j;}}scanf("%d",&k);while(k--){cin>>s;if(s[0]=='N'){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(ma[i][j]=='*'){ma[i][j]='.';for(int l=i-1;l>=1;l--){if(ma[l][j]=='X')break;ma[l][j]='#';}}}}}if(s[0]=='S'){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(ma[i][j]=='*'){ma[i][j]='.';for(int l=i+1;l<=n;l++){if(ma[l][j]=='X')break;ma[l][j]='#';}}}}}if(s[0]=='W'){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(ma[i][j]=='*'){ma[i][j]='.';for(int l=j-1;l>=1;l--){if(ma[i][l]=='X')break;ma[i][l]='#';}}}}}if(s[0]=='E'){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(ma[i][j]=='*'){ma[i][j]='.';for(int l=j+1;l<=m;l++){if(ma[i][l]=='X')break;ma[i][l]='#';}}}}}for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(ma[i][j]=='#')ma[i][j]='*';}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){printf("%c",ma[i][j]);}printf("\n");}
}
/*
4 5
.....
.X...
...*X
X.X..
3
NORTH
WEST
SOUTH*/

总结:

终于搜索完了,希望多复习,多温故,多有新的理解

9.14~9.15集训小结相关推荐

  1. AI:2020年6月21日北京智源大会演讲分享之14:50-15:15穗志方教授《从语言到知识——构建语言智能的基石》

    AI:2020年6月21日北京智源大会演讲分享之14:50-15:15穗志方教授<从语言到知识--构建语言智能的基石> 导读:首先感谢北京智源大会进行主题演讲的各领域顶级教授,博主受益匪浅 ...

  2. 2023款ThinkBook 14和15锐龙版区别对比评测选哪个好

    屏幕的区别: 2023款ThinkBook 14锐龙版其屏幕的尺寸是14英寸,屏幕占比为85%,而2023款ThinkBook 15锐龙版的屏幕尺寸为15.6英寸,屏幕占比是88%,相比之下,Thin ...

  3. 4月14日~15日,2021慕尼黑上海电子展,我等你来!

    关注+星标公众号,不错过精彩内容 转自 | 达尔闻说 4月14日~15日,2021慕尼黑上海电子展,有小伙伴要去吗?(我要去,但我不告诉你) 3分钟快速了解得捷时刻,片尾有惊喜 4月14与4月15日, ...

  4. 2021.8.8 ~ 2021.8.14 在SSL集训总结(Week 1 已更完)

    集训总结 前言 因为疫情,就回到SSL集训了 (可能有点长,右边有目录) 后续,第二周 2021.8.15 ~ 2021.8.25 在SSL集训总结(Week 2)(更新ing) Day -1(8.7 ...

  5. 在 Ubuntu 14.04/15.04 上配置 Node JS v4.0.0

    大家好,Node.JS 4.0 发布了,这个流行的服务器端 JS 平台合并了 Node.js 和 io.js 的代码,4.0 版就是这两个项目结合的产物--现在合并为一个代码库.这次最主要的变化是 N ...

  6. LSMW批处理使用方法(11)_步骤14、15

    步骤14:转换数据 本步骤是将读进系统文件的数据进行转换,存放在步骤10指定源表文件"Converted Data"指定的转换文件中.本步骤和下一步骤显示可以查看转换是否正确,如不 ...

  7. 11.14/11.15 Apache和PHP结合 11.16/11.17 Apache默认虚拟主机

    2019独角兽企业重金招聘Python工程师标准>>> 11.14-11.15 Apache和PHP结合 Apache(httpd)的配置文件:/usr/local/apache2. ...

  8. 第14、15教学周作业

    要求一 还差一些没做完. 要求二 USTH_C程序设计(基础)14周第一次PTA作业 7-3 将数组中的数逆序存放 1.实验代码 #include<stdio.h>int main() { ...

  9. 蔡高厅老师 - 高等数学阅读笔记 - 03 - 极限(13、14、15、16、17)

    13 函数极限性质 极限的四则运算公式 证明3 性质4: 再求分子极限 14 极限存在准则和两个重要极限 1 准则一:夹挤准则 2 重要的极限 15.16 利用单位圆证明:三个重要线段 3 准则2 - ...

最新文章

  1. 安装模拟器遇到的问题
  2. c++ 读文件_C语言处理文件基础知识:文件、流和键盘输入
  3. jquery 向上滚动【四】个人认为好一些,哈
  4. java中数值023是什么类型_【Java 教程(原创)】023.参数传值——引用类型参数的传值...
  5. 数据库备份DBS 新增Region支持:华北2、华东2和华南1
  6. 垃圾收集算法,垃圾收集器_您正在使用什么垃圾收集器?
  7. GLTF格式——关系描述
  8. 程序员如何掌握 React 开发的黄金法则? | 技术头条
  9. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明),签到题HIL
  10. MYSQL 存储过程和函数 案例 例子
  11. 铜带屏蔽计算机电缆故障,计算机电缆DJYPVP22-300/500V-2*2*1.0价格
  12. ADSL密码查看器绿色版
  13. arcgis使用教程和视频教程
  14. 傲梅分区助手克隆Linux硬盘,傲梅分区助手怎么复制磁盘?分区助手克隆磁盘的具体方法...
  15. 急!有谁知道如何截获WebBrowser控件的 ie脚本错误提示 吗?
  16. 熊市之后!除了割肉就是割肉!(爆笑漫画)
  17. iMazing中IPA文件的介绍与管理
  18. 僵尸java7723_僵尸王国7723游戏盒子
  19. LQ0141 纸张尺寸【水题】
  20. Windows怎么删除多余的右键打开方式

热门文章

  1. 环保材料营造健康氛围
  2. arcgis server发布shp服务实现数据库更新后服务也相应更新数据
  3. 机器学习基础-23:矩阵理论(L0/L1/L2范数等)
  4. java原生和SpringBoot读取jar包中MANIFEST.MF的方式
  5. 小实践之网络打印机的设置(实际操作篇)
  6. AD8066ARZ介绍
  7. 昨晚,奔奔第一次哭伤心了。。。
  8. RK3588 Android平台SPI NOR+PCIE SSD实现大容量存储方案
  9. Witt向量简介 §4.1:关于组合数是整数的一种严格证明
  10. 从电焊女工到Google台湾总经理