第二次双周赛
2-1 输出全排列
题目描述
思路分析
标准的板子题,DFS+数组记录
即可。
#include<bits/stdc++.h>
using namespace std;
int n;
int vis[15];
int a[15];
void dfs(int num){
if (num==n){
for (int i=1; i<=n; i++)
cout<<a[i];
cout<<endl;
return;
}
for (int i=1; i<=n; i++){
if (!vis[i]){
a[num+1]=i;
vis[i]=1;
dfs(num+1);
vis[i]=0;
}
}
}
int main(){
cin>>n;
for (int i=1; i<=n; i++){
vis[i]=1;
a[1]=i;
dfs(1);
vis[i]=0;
}
//system("pause");
return 0;
}
注意:
a[num+1]=i;
不可写成a[++num]=i;
比赛卡死在这个地方很久,再一次喜提T1用时倒数
2-2 山
题目描述
思路分析
可以用DFS
,如果当前的点没有被扫描过,就说明这是一个新的山峰,并且以此为一个起点,去拓展出整个山峰,将这个点相邻的点均打下标记,即vis[i]=1
。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+5;
int n,m;
int num=0;
int a[maxn][maxn];
int vis[maxn][maxn];
int d1[4]={-1,0,0,1};
int d2[4]={0,-1,1,0};
struct node{
int x;
int y;
};
queue <node> q;
void dfs(int x,int y){
if (vis[x][y])
return;
if (a[x][y] && !vis[x][y]){
q.push(node{x,y});
num++;
vis[x][y]=num;
while (!q.empty()){
int nx=q.front().x;
int ny=q.front().y;
q.pop();
for (int i=0; i<4; i++){
int tx=nx+d1[i];
int ty=ny+d2[i];
if (tx>=1 && tx<=n && ty>=1 && ty<=m && a[tx][ty] && !vis[tx][ty]){
q.push(node{tx,ty});
vis[tx][ty]=num;
}
}
}
}
}
int main(){
int sx,sy;
cin>>n>>m;
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++){
cin>>a[i][j];
}
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++){
dfs(i,j);
}
cout<<num;
return 0;
}
2-3 跳跃
题目描述
解题思路
这道题很类似 P1135 奇怪的电梯 其实肯定是祝神CV来的
这道题更简化了,甚至不需要输出最小步数,所以DFS
和BFS
时间复杂度理论上差不多了。
然而,在你连续WA
了几发后,在你DFS
和BFS
各写了一遍都不对后,在你经过了题目怀疑、数据怀疑、自我怀疑、人生怀疑后,就会很轻松 地发现,原来下标是从0
开始的!!!(认真读数据范围)
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int a[maxn];
int st,n;
int vis[maxn];
bool jud=0;
void dfs(int x){
if (jud){
return;
}
int step=a[x];
if (!step){
jud=1;
return;
}
int to1=x-step;
int to2=x+step;
if (to1>=0 && to1<n && !vis[to1]){
vis[to1]=1;
dfs(to1);
}
if (to2<n && to2>1 && !vis[to2]){
vis[to2]=1;
dfs(to2);
}
}
int main(){
cin>>n;
for (int i=0; i<n; i++)
cin>>a[i];
cin>>st;
vis[st]=1;
dfs(st);
if (jud){
cout<<"True";
}
else
cout<<"False";
//system("pause");
return 0;
}
2-4 回文数文回
题目描述
解题思路
思路一:枚举前五位数字
由回文数的特征可知,九位回文数只需知道前五位即可确定,所以只需枚举前五位数字即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e9+5;
const int st=1e8;
int main(){
int n;
int num=0;
cin>>n;
string s;
s=to_string(n);
int a,b,c,d;
a=s[0]-'0';
b=s[1]-'0';
c=s[2]-'0';
d=s[3]-'0';
for (int a1=1; a1<=a; a1++)
for (int b1=0; b1<=9; b1++)
for (int c1=0; c1<=9; c1++)
for (int d1=0; d1<=9; d1++)
for (int e1=0; e1<=9; e1++){
int k=a1*100000000+b1*10000000+c1*1000000+d1*100000+e1*10000+d1*1000+c1*100+b1*10+a1;
if (k<=n){
num++;
}
}
cout<<num;
return 0;
}
思路2:打表
最大1e9
,打表即可。可以找一个合适的间隔,保证每次只需算间隔内的数即可。注意这个间隔不能太大,太大会超时;也不能太小,间隔过于密集会导致代码长度超过限制16KB
。我找了1e6
的间隔。
#include<bits/stdc++.h>
using namespace std;
const int section_num=1e4+5;
const int maxn=1e9+5;
const int st=1e8;
int a[section_num]={0,100,200,300,400,500,600,700,800,900,1000,1100,1200,1300,1400,1500,1600,1700,1800,1900,2000,2100,2200,2300,2400,2500,2600,2700,2800,2900,3000,3100,3200,3300,3400,3500,3600,3700,3800,3900,4000,4100,4200,4300,4400,4500,4600,4700,4800,4900,5000,5100,5200,5300,5400,5500,5600,5700,5800,5900,6000,6100,6200,6300,6400,6500,6600,6700,6800,6900,7000,7100,7200,7300,7400,7500,7600,7700,7800,7900,8000,8100,8200,8300,8400,8500,8600,8700,8800,8900,9000,9100,9200,9300,9400,9500,9600,9700,9800,9900,10000,10100,10200,10300,10400,10500,10600,10700,10800,10900,11000,11100,11200,11300,11400,11500,11600,11700,11800,11900,12000,12100,12200,12300,12400,12500,12600,12700,12800,12900,13000,13100,13200,13300,13400,13500,13600,13700,13800,13900,14000,14100,14200,14300,14400,14500,14600,14700,14800,14900,15000,15100,15200,15300,15400,15500,15600,15700,15800,15900,16000,16100,16200,16300,16400,16500,16600,16700,16800,16900,17000,17100,17200,17300,17400,17500,17600,17700,17800,17900,18000,18100,18200,18300,18400,18500,18600,18700,18800,18900,19000,19100,19200,19300,19400,19500,19600,19700,19800,19900,20000,20100,20200,20300,20400,20500,20600,20700,20800,20900,21000,21100,21200,21300,21400,21500,21600,21700,21800,21900,22000,22100,22200,22300,22400,22500,22600,22700,22800,22900,23000,23100,23200,23300,23400,23500,23600,23700,23800,23900,24000,24100,24200,24300,24400,24500,24600,24700,24800,24900,25000,25100,25200,25300,25400,25500,25600,25700,25800,25900,26000,26100,26200,26300,26400,26500,26600,26700,26800,26900,27000,27100,27200,27300,27400,27500,27600,27700,27800,27900,28000,28100,28200,28300,28400,28500,28600,28700,28800,28900,29000,29100,29200,29300,29400,29500,29600,29700,29800,29900,30000,30100,30200,30300,30400,30500,30600,30700,30800,30900,31000,31100,31200,31300,31400,31500,31600,31700,31800,31900,32000,32100,32200,32300,32400,32500,32600,32700,32800,32900,33000,33100,33200,33300,33400,33500,33600,33700,33800,33900,34000,34100,34200,34300,34400,34500,34600,34700,34800,34900,35000,35100,35200,35300,35400,35500,35600,35700,35800,35900,36000,36100,36200,36300,36400,36500,36600,36700,36800,36900,37000,37100,37200,37300,37400,37500,37600,37700,37800,37900,38000,38100,38200,38300,38400,38500,38600,38700,38800,38900,39000,39100,39200,39300,39400,39500,39600,39700,39800,39900,40000,40100,40200,40300,40400,40500,40600,40700,40800,40900,41000,41100,41200,41300,41400,41500,41600,41700,41800,41900,42000,42100,42200,42300,42400,42500,42600,42700,42800,42900,43000,43100,43200,43300,43400,43500,43600,43700,43800,43900,44000,44100,44200,44300,44400,44500,44600,44700,44800,44900,45000,45100,45200,45300,45400,45500,45600,45700,45800,45900,46000,46100,46200,46300,46400,46500,46600,46700,46800,46900,47000,47100,47200,47300,47400,47500,47600,47700,47800,47900,48000,48100,48200,48300,48400,48500,48600,48700,48800,48900,49000,49100,49200,49300,49400,49500,49600,49700,49800,49900,50000,50100,50200,50300,50400,50500,50600,50700,50800,50900,51000,51100,51200,51300,51400,51500,51600,51700,51800,51900,52000,52100,52200,52300,52400,52500,52600,52700,52800,52900,53000,53100,53200,53300,53400,53500,53600,53700,53800,53900,54000,54100,54200,54300,54400,54500,54600,54700,54800,54900,55000,55100,55200,55300,55400,55500,55600,55700,55800,55900,56000,56100,56200,56300,56400,56500,56600,56700,56800,56900,57000,57100,57200,57300,57400,57500,57600,57700,57800,57900,58000,58100,58200,58300,58400,58500,58600,58700,58800,58900,59000,59100,59200,59300,59400,59500,59600,59700,59800,59900,60000,60100,60200,60300,60400,60500,60600,60700,60800,60900,61000,61100,61200,61300,61400,61500,61600,61700,61800,61900,62000,62100,62200,62300,62400,62500,62600,62700,62800,62900,63000,63100,63200,63300,63400,63500,63600,63700,63800,63900,64000,64100,64200,64300,64400,64500,64600,64700,64800,64900,65000,65100,65200,65300,65400,65500,65600,65700,65800,65900,66000,66100,66200,66300,66400,66500,66600,66700,66800,66900,67000,67100,67200,67300,67400,67500,67600,67700,67800,67900,68000,68100,68200,68300,68400,68500,68600,68700,68800,68900,69000,69100,69200,69300,69400,69500,69600,69700,69800,69900,70000,70100,70200,70300,70400,70500,70600,70700,70800,70900,71000,71100,71200,71300,71400,71500,71600,71700,71800,71900,72000,72100,72200,72300,72400,72500,72600,72700,72800,72900,73000,73100,73200,73300,73400,73500,73600,73700,73800,73900,74000,74100,74200,74300,74400,74500,74600,74700,74800,74900,75000,75100,75200,75300,75400,75500,75600,75700,75800,75900,76000,76100,76200,76300,76400,76500,76600,76700,76800,76900,77000,77100,77200,77300,77400,77500,77600,77700,77800,77900,78000,78100,78200,78300,78400,78500,78600,78700,78800,78900,79000,79100,79200,79300,79400,79500,79600,79700,79800,79900,80000,80100,80200,80300,80400,80500,80600,80700,80800,80900,81000,81100,81200,81300,81400,81500,81600,81700,81800,81900,82000,82100,82200,82300,82400,82500,82600,82700,82800,82900,83000,83100,83200,83300,83400,83500,83600,83700,83800,83900,84000,84100,84200,84300,84400,84500,84600,84700,84800,84900,85000,85100,85200,85300,85400,85500,85600,85700,85800,85900,86000,86100,86200,86300,86400,86500,86600,86700,86800,86900,87000,87100,87200,87300,87400,87500,87600,87700,87800,87900,88000,88100,88200,88300,88400,88500,88600,88700,88800,88900,89000,89100,89200,89300,89400,89500,89600,89700,89800,89900,100000};
int main(){
int n;
int num=0;
cin>>n;
num+=a[(n-st)/1000000];
for (int i=st+(n-st)/1000000*1000000+1; i<=n; i++)
{
string s;
s=to_string(i);
bool jud=0;
for (int i=0,j=8; i<4; i++,j--){
if (s[i]!=s[j]){
jud=1;
break;
}
}
if (!jud){
num++;
}
}
cout<<num;
//system("pause");
return 0;
}
2-5 最长光路
题目描述
思路分析
DFS
分析四个方向即可,需要用到三维数组vis
来记录这个方向上是否拜访过。如果一个地方并且其对应的方向被拜访了两次,就说明这是一个环。
ps:题目貌似只说明了如果光源朝各个方向摆设,最终光线都会射向盒子外部,那么小明认为经过格子最多的光路是最酷的
,但是没说明射不出盒子外部时的情况下,最酷的也是格子最多的。看了测试数据才明白的QAQ
#include <bits/stdc++.h>
using namespace std;
const int maxn=500+5;
int n,m;
char c[maxn][maxn];
int sx,sy;
int d1[4]={-1,0,1,0};
int d2[4]={0,1,0,-1};
int d3[4]={0,1,2,3};
int vis[maxn][maxn][4];
int ans=0,preans=0;
bool jud=0;
void dfs(int x,int y,int d,int num){
if (jud){
return;
}
int dx=x;
int dy=y;
while (1){
dx=dx+d1[d];
dy=dy+d2[d];
num++;
if (!(dx>=1 && dx<=n && dy>=1 && dy<=m)){
ans=max(ans,num);
return;
}
if (vis[dx][dy][d]){
ans=-1;
jud=1;
return;
}
if (c[dx][dy]=='\\'){
int td;
switch (d){
case 0:td=3;break;
case 1:td=2;break;
case 2:td=1;break;
case 3:td=0;break;
}
if (vis[dx][dy][td]){
ans=-1;
jud=1;
return;
}
vis[dx][dy][td]=1;
dfs(dx,dy,td,num);
vis[dx][dy][td]=0;
return;
}
if (c[dx][dy]=='/'){
int td;
switch (d){
case 0:td=1;break;
case 1:td=0;break;
case 2:td=3;break;
case 3:td=2;break;
}
if (vis[dx][dy][td]){
ans=-1;
jud=1;
return;
}
vis[dx][dy][td]=1;
dfs(dx,dy,td,num);
vis[dx][dy][td]=0;
return;
}
if (c[dx][dy]=='C'){
ans=max(ans,num);
return;
}
if (c[dx][dy]=='.'){
continue;
}
}
}
int main(){
cin>>n>>m;
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
cin>>c[i][j];
cin>>sx>>sy;
int maxd=-1;
for (int i=0; i<4; i++){
vis[sx][sy][i]=1;
dfs(sx,sy,i,0);
vis[sx][sy][i]=0;
if (ans!=preans){
maxd=i;
}
if (ans==-1){
break;
}
preans=ans;
}
switch (maxd){
case 0:cout<<"U"<<endl; break;
case 1:cout<<"R"<<endl; break;
case 2:cout<<"D"<<endl; break;
case 3:cout<<"L"<<endl; break;
}
if (ans==-1){
cout<<"COOL";
}
else
cout<<ans;
//system("pause");
return 0;
}