这次集训主要是对于基本逻辑还有基本算法的训练,基本算法就是对于并查集,深度优先搜索,广度优先搜索一些理解与应用,选的题都是比较适合入门的题,比较简单。
A:
一道几何题,我没有做,放下题解代码。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int T,a,b;
const double pi=3.1415926535897932;
enum type
{
EMPTY=0,
FULL=1,
FLE=2,
FGE=3,
ELF=4,
EGF=5,
FLEFL=6,
FGEFL=7,
FLEFG=8,
ELFEL=9,
EGFEL=10,
ELFEG=11,
};
void gettype(int a,int b,int& tar,int& t1,int& t2)
{
if(a>=180)
{
if(b>a)tar=FULL;
else if(b<=90)tar=FGE,t1=b;
else if(b<180)tar=FLE,t1=b;
else tar=EMPTY;
}else if(a<90)
{
if(b>=180||b==0)tar=EGF,t1=a;
else if(b>90)tar=FLEFL,t1=b,t2=a;
else if(b>a)tar=FGEFL,t1=b,t2=a;
else if(b>0)tar=EGFEL,t1=a,t2=b;
}else if(a>=90)
{
if(b>=180||b==0)tar=ELF,t1=a;
else if(b<=90)tar=ELFEL,t1=a,t2=b;
else if(b<a)tar=ELFEG,t1=a,t2=b;
else if(b<180)tar=FLEFG,t1=b,t2=a;
}
}
double torad(double d)
{
return pi/180.0*d;
}
double gettotal(int t,double t1,double t2)
{
if(t==EMPTY)return 0.0;
if(t==FULL)return 1.0;
if(t==FLE)return sin(t1);
if(t==FGE)return 1.0;
if(t==ELF)return 1.0;
if(t==EGF)return sin(t1);
if(t==FLEFL)return max(sin(t1),sin(t2));
if(t==FGEFL)return 1.0;
if(t==FLEFG)return 1.0;
if(t==ELFEL)return 1.0;
if(t==EGFEL)return sin(t1);
if(t==ELFEG)return sin(t2);
}
double getred(int t,double t1,double t2)
{
if(t==EMPTY)return 0.0;
if(t==FULL)return 0.0;
if(t==FLE)return sin(t1);
if(t==FGE)return sin(t1);
if(t==ELF)return 0.0;
if(t==EGF)return 0.0;
if(t==FLEFL)return max(0.0,sin(t1)-sin(t2));
if(t==FGEFL)return sin(t1)-sin(t2);
if(t==FLEFG)return 0.0;
if(t==ELFEL)return sin(t2);
if(t==EGFEL)return sin(t2);
if(t==ELFEG)return sin(t2);
}
int tl,tr;
int tl1,tl2,tr1,tr2;
int main()
{
cin>>T;
while(T--)
{
cin>>a>>b;
gettype(a,b,tr,tr1,tr2);
a=(-a+360)%360;
b=(-b+360)%360;
swap(a,b);
gettype(a,b,tl,tl1,tl2);
double totl=gettotal(tl,torad(tl1),torad(tl2));
double totr=gettotal(tr,torad(tr1),torad(tr2));
double redl=getred(tl,torad(tl1),torad(tl2));
double redr=getred(tr,torad(tr1),torad(tr2));
printf("%.1lf%%\n",(redl+redr)*100.0/(totl+totr));
}
return 0;
}
B题:
一道关于异或的线性基问题。
/*
求线性基即可
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 55
using namespace std;
int n;
long long a[maxn],b[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
for(int j=50;j>=0;j--){
if((a[i]>>j)&1){
if(b[j])a[i]^=b[j];
else {
b[j]=a[i];
for(int k=j-1;k>=0;k--)if((b[j]>>k)&1)b[j]^=b[k];
for(int k=j+1;k<=50;k++)if((b[k]>>j)&1)b[k]^=b[j];
break;
}
}
}
}
long long ans=0;
for(int i=0;i<=50;i++)ans^=b[i];
cout<<ans;
return 0;
}
C题:
一道简单的搜索,我采用了深搜和广搜俩种写法。不懂得可以看看。
# include <iostream>
# include <queue>
# include <cstring>
using namespace std;
const int maxn = 25;
bool vis[maxn][maxn];
char str[maxn][maxn];
int n, m, sx, sy, ex,ey;
int dis[][2] = {0, 1, 0, -1, 1, 0, -1, 0};
struct node
{
int x, y;
};
# if 0
bool bfs()
{
queue<struct node> q;
struct node temp, front;
front.x = sx;
front.y = sy;
q.push(front);
while(!q.empty())
{
temp = q.front();
q.pop();
if(temp.x == ex && temp.y == ey)
{
return true;
}
for(int i = 0; i < 4; i++)
{
int tx = temp.x + dis[i][0];
int ty = temp.y + dis[i][1];
if(str[tx][ty] != '.' || tx < 0 || tx >= n || ty < 0 ||ty >= m)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = 1;
front.x = tx;
front.y = ty;
q.push(front);
}
}
}
return false;
}
# endif
bool flag;
void dfs(int x, int y)
{
if(flag)
{
return ;
}
if(x == ex && y == ey)
{
flag = true;
return ;
}
for(int i = 0; i < 4; i++)
{
int tx = x + dis[i][0];
int ty = y + dis[i][1];
if(str[tx][ty] != '.' || tx < 0 || tx >= n || ty < 0 ||ty >= m)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = true;
dfs(tx, ty);
vis[tx][ty] = false;
}
}
}
int main(int argc, char *argv[])
{
while(cin >> m >> n, (m||n))
{
flag = false;
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; i++)
{
cin >> str[i];
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(str[i][j] == 'S')
{
sx = i;
sy = j;
}
if(str[i][j] == 'P')
{
str[i][j] = '.';
ex = i;
ey = j;
}
}
}
# if 0
if(bfs())
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
# endif
dfs(sx, sy);
if(flag)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
return 0;
}
D题:
阶乘问题。
# include <iostream>
# include <queue>
# include <cstring>
using namespace std;
const int maxn = 25;
int a[13];
void fun()
{
int k = 1;
for(int i = 1; i <= 12; i++)
{
k *= i;
a[i] = k;
}
}
int main(int argc, char *argv[])
{
int n;
fun();
while(cin >> n)
{
while(n--)
{
int m;
cin >> m;
cout << a[m] <<endl;
}
}
return 0;
}
E:
一道简单的dp问题,又是一道记忆化搜索的简单应用
# include <iostream>
# include <queue>
# include <cstring>
using namespace std;
const int maxn = 26;
int dp[maxn][maxn][maxn];
const int maxx = 0x3f3f3f3f;
void fun()
{
for(int i = 0; i < 26; i++)
{
for(int j = 0; j < 26; j++)
{
for(int k = 0; k < 26; k++)
{
dp[i][j][k] = maxx;
}
}
}
}
int w(int a, int b, int c)
{
if(dp[a][b][c] != maxx)
{
return dp[a][b][c];
}
if(a <= 0 || b <= 0 || c <= 0)
{
return 1;
}
if(a > 20 || b > 20 || c > 20)
{
return w(20, 20, 20);
}
if(a < b && b < c)
{
dp[a][b][c] = w(a, b, c-1) + w(a, b-1, c-1) - w(a, b-1, c);
}
else
{
dp[a][b][c] = w(a-1, b, c) + w(a-1, b-1, c) + w(a-1, b, c-1) - w(a-1, b-1, c-1);
}
return dp[a][b][c];
}
int main(int argc, char *argv[])
{
int n;
while(cin >> n)
{
while(n--)
{
fun();
int a, b, c;
cin >> a >> b >> c;
cout << w(a, b, c) << endl;
}
}
return 0;
}
F题:
# include <iostream>
# include <queue>
# include <cstring>
# include <iomanip>
using namespace std;
const int maxn = 26;
int dp[maxn][maxn][maxn];
const int maxx = 0x3f3f3f3f;
int main(int argc, char *argv[])
{
double x;
while(cin >> x)
{
cout << fixed << setprecision(1);
if(x > 0)
{
cout << x * x + 1 << endl;
}
else if(x < 0)
{
cout << -x << endl;
}
else
{
cout << 100.00 << endl;
}
}
return 0;
}
G题:
打印杨辉三角
# include <iostream>
# include <queue>
# include <cstring>
# include <iomanip>
using namespace std;
const int maxn = 35;
int dp[maxn][maxn];
const int maxx = 0x3f3f3f3f;
int main(int argc, char *argv[])
{
int n;
while(cin >> n, n)
{
memset(dp, false, sizeof(dp));
dp[1][1] = 1;
for(int i = 2; i <= n; i++)
{
for(int j = 1; j <= i; j++)
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1];
}
for(int i = 1; i <= n; i++)
{
int p = 0;
for(int j = 1; j <= i; j++)
{
if(p++)
{
cout << " ";
}
cout << dp[i][j];
}
cout << endl;
}
cout << endl;
}
return 0;
}
H题:
可以找规律也可以用数学的方法来做,因为根据一个大数模除一个数,可以拆成好多个小的数模除一个数然后相加在模除
# include <iostream>
# include <queue>
# include <cstring>
# include <iomanip>
using namespace std;
const int maxn = 35;
int dp[maxn][maxn];
const int maxx = 0x3f3f3f3f;
int main(int argc, char *argv[])
{
int n;
while(cin >> n)
{
if(n < 2)
{
cout << "no" << endl;
}
else
{
int a = 7, b = 11, c;
for(int i = 2; i <= n; i++)
{
c = (a + b) % 3;
a = b;
b = c;
}
if(c)
{
cout << "no" << endl;
}
else
{
cout << "yes" << endl;
}
}
}
return 0;
}
I题:
# include <iostream>
# include <queue>
# include <cstring>
# include <iomanip>
using namespace std;
const int maxn = 45;
int dp[maxn];
const int maxx = 0x3f3f3f3f;
void fun()
{
dp[1] = 1, dp[2] = 1;
for(int i = 3; i <= 41; i++)
{
dp[i] = dp[i - 1] + dp[i - 2];
}
}
int main(int argc, char *argv[])
{
int n;
fun();
while(cin >> n)
{
int p = 0;
for(int i = 1; i <= n; i++)
{
if(p++)
{
cout << " ";
}
cout << dp[i];
}
cout << endl;
}
return 0;
}
J题:
简单递归。
# include <iostream>
# include <queue>
# include <cstring>
# include <iomanip>
using namespace std;
const int maxn = 45;
int dp[maxn];
const int maxx = 0x3f3f3f3f;
int fun(int x)
{
if(x == 1)
{
return 10;
}
return fun(x - 1) + 2;
}
int main(int argc, char *argv[])
{
int n;
while(cin >> n)
{
cout << fun(n) << endl;
}
return 0;
}
K题:
一道水的并查集只要判断输入的数根是不是相同就行。相同说明就有俩条以上的路不同就合并然后继续输入。
# include <iostream>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxn = 100005;
int pre[maxn];
int find(int x)
{
if(x != pre[x])
{
pre[x] = find(pre[x]);
}
return pre[x];
}
void join(int x, int y)
{
int tx = find(x);
int ty = find(y);
if(tx != ty)
{
pre[ty] = tx;
}
}
void fun()
{
for(int i = 0; i < maxn; i++)
{
pre[i] = i;
}
}
int main(int argc, char *asrgv[])
{
int x, y;
fun();
bool flag = false;
while(cin >> x >> y, x != - 1 && y!= -1)
{
if(x == 0 && y == 0)
{
if(!flag)
{
cout << "Yes" << endl;
}
else
{
cout << "No" << endl;
}
flag = false;
fun();
}
else
{
if(!flag)
{
if(find(x) != find(y))
{
join(x, y);
}
else
{
flag = true;
}
}
}
}
return 0;
}
L题:
找一下一有几个不同的根就行然后-1就是需要修的路
# include <iostream>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxn = 100005;
int pre[maxn];
int find(int x)
{
if(x != pre[x])
{
pre[x] = find(pre[x]);
}
return pre[x];
}
void join(int x, int y)
{
int tx = find(x);
int ty = find(y);
if(tx != ty)
{
pre[ty] = tx;
}
}
void fun()
{
for(int i = 0; i < maxn; i++)
{
pre[i] = i;
}
}
int main(int argc, char *asrgv[])
{
int n, m;
while(cin >> n >> m)
{
fun();
for(int i = 0; i < m; i++)
{
int x, y;
cin >> x >> y;
join(x, y);
}
int arr[maxn] = {0};
for(int i = 1; i <= n; i++)
{
arr[find(pre[i])]++;
}
int sum = 0;
for(int i = 0; i <= n; i++)
{
if(arr[i])
{
sum++;
}
}
cout << sum - 1 << endl;
}
return 0;
}
M题:
换汤不换药还是问有几个根的问题。
# include <iostream>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxn = 100005;
int pre[maxn];
int find(int x)
{
if(x != pre[x])
{
pre[x] = find(pre[x]);
}
return pre[x];
}
void join(int x, int y)
{
int tx = find(x);
int ty = find(y);
if(tx != ty)
{
pre[ty] = tx;
}
}
void fun()
{
for(int i = 0; i < maxn; i++)
{
pre[i] = i;
}
}
int main(int argc, char *asrgv[])
{
int n, m;
int t;
while(cin >> t)
{
while(t--)
{
cin >> n >> m;
fun();
for(int i = 0; i < m; i++)
{
int x, y;
cin >> x >> y;
join(x, y);
}
int arr[maxn] = {0};
for(int i = 1; i <= n; i++)
{
arr[find(pre[i])]++;
}
int sum = 0;
for(int i = 0; i <= n; i++)
{
if(arr[i])
{
sum++;
}
}
cout << sum << endl;
}
}
return 0;
}
N题:
换汤不换药还是问有几个不同的根
# include <iostream>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxn = 100005;
int pre[maxn];
int find(int x)
{
if(x != pre[x])
{
pre[x] = find(pre[x]);
}
return pre[x];
}
void join(int x, int y)
{
int tx = find(x);
int ty = find(y);
if(tx != ty)
{
pre[ty] = tx;
}
}
void fun()
{
for(int i = 0; i < maxn; i++)
{
pre[i] = i;
}
}
int main(int argc, char *asrgv[])
{
int n, m;
int t;
while(cin >> n)
{
if(n == 0)
{
break;
}
cin >> m;
fun();
for(int i = 0; i < m; i++)
{
int x, y;
cin >> x >> y;
join(x, y);
}
int arr[maxn] = {0};
for(int i = 1; i <= n; i++)
{
arr[find(pre[i])]++;
}
int sum = 0;
for(int i = 0; i <= n; i++)
{
if(arr[i])
{
sum++;
}
}
cout << sum << endl;
}
return 0;
}
O题:
还是问有几个不同的根,然后注意下特判下有没有朋友关系
# include <iostream>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxn = 100005;
int pre[maxn];
int find(int x)
{
if(x != pre[x])
{
pre[x] = find(pre[x]);
}
return pre[x];
}
void join(int x, int y)
{
int tx = find(x);
int ty = find(y);
if(tx != ty)
{
pre[ty] = tx;
}
}
void fun()
{
for(int i = 0; i < maxn; i++)
{
pre[i] = i;
}
}
int main(int argc, char *asrgv[])
{
int n, m;
int t;
while(cin >> t)
{
while(t--)
{
cin >> n >> m;
fun();
for(int i = 0; i < m; i++)
{
int x, y;
cin >> x >> y;
join(x, y);
}
int arr[maxn] = {0};
for(int i = 1; i <= n; i++)
{
arr[find(pre[i])]++;
}
bool flag = false;
int sum1 = 0, sum2 = 0;
for(int i = 1; i <= n; i++)
{
if(arr[i] > 1)
{
flag = true;
sum1++;
}
if(arr[i])
{
sum2++;
}
}
// cout << "sum1 = " << sum1 << " " << "sum2 = " << sum2 << endl;
if(flag)
{
cout <<sum2 <<endl;
}
else
{
cout << n << endl;
}
}
}
return 0;
}
P题:
这是一个关于栈的问题,要求符合栈的顺序输出。可以拿栈来模拟。理解题意就是一道水题了
#include<cstdio>
#include<stack>
#include<iostream>
using namespace std;
int a[1000];
int main()
{
int n,i,k;
while(scanf("%d",&n)&&n)
{
stack <int> s;
while(scanf("%d",&a[0])&&a[0])
{
for(i=1;i<n;i++)
cin >> a[i];
//找到我对应的然后全退出去
for(i=1,k=0;i<=n;i++)
{
s.push(i);
while(s.top()==a[k])
{
if(!s.empty())
s.pop();
k++;
if(s.empty())
break;
}
}
if(k==n)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
cout << endl;
}
return 0;
}
Q题:
最小生成树问题,可以用克鲁斯卡尔算法求解也可以用,prim算法,我用的克鲁斯卡尔算法。
# include <iostream>
# include <cstring>
# include <algorithm>
# include <iomanip>
# include <cstdio>
using namespace std;
const int maxn = 100005;
struct node
{
int x, y;
double z;
}f[maxn];
int pre[maxn];
int find(int x)
{
if(x != pre[x])
{
pre[x] = find(pre[x]);
}
return pre[x];
}
void join(int x, int y)
{
int tx = find(x);
int ty = find(y);
if(tx != ty)
{
pre[ty] = tx;
}
}
void fun()
{
for(int i = 0; i < maxn; i++)
{
pre[i] = i;
f[i].x = f[i].y = f[i].z = 0;
}
}
bool cmp(node a, node b)
{
return a.z < b.z;
}
int main(int argc, char *asrgv[])
{
double s;
cin >> s;
{
fun();
int n, m;
cin >> n ;
m = 0;
while(cin >> f[m].x >> f[m].y >> f[m].z)
{
// cout << f[m].x << "--" << f[m].y << "--" << f[m].z << endl;
m++;
}
sort(f, f + m, cmp);
int num = 0;
double ss = 0;
for(int i = 0; i < m; i++)
{
if(find(f[i].x) != find(f[i].y))
{
// cout << f[i].x << "--" << f[i].y << "--" << f[i].z << endl;
join(f[i].x, f[i].y);
num++;
ss += f[i].z;
}
if(num == n - 1)
{
break;
}
}
if(ss <= s && num == n - 1)
{
cout << fixed << setprecision(2);
cout << "Need "<< ss<<" miles of cable" <<endl;
}
else
{
cout << "Impossible" <<endl;
}
}
return 0;
}
R题:
一道搜索题,需要计算杀掉守卫快还是绕路快。然后让优先级高的先出队,我这里采用了优先队列应该可以设一个变量做一下标记,遇见守卫后出队也可以。
# include <iostream>
# include <queue>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxn = 205;
const int maxx = 0x3f3f3f3f;
bool vis[maxn][maxn];
char str[maxn][maxn];
int n, m, t,sx, sy, ex,ey;
int dis[][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int num;
struct node
{
int x, y, t;
}s[maxn];
struct cmp
{
bool operator () (const node a, const node b)
{
return a.t > b.t;
}
};
bool bfs()
{
priority_queue<node, vector<node>, cmp> q;
struct node temp, f;
for(int i = 0; i < num; i++)
{
f.x = s[i].x;
f.y = s[i].y;
f.t = 0;
q.push(f);
}
while(!q.empty())
{
temp = q.top();
q.pop();
if(temp.x == ex && temp.y == ey && temp.t < t)
{
t = temp.t;
}
for(int i = 0; i < 4; i++)
{
int tx = temp.x + dis[i][0];
int ty = temp.y + dis[i][1];
if(str[tx][ty] == '#' || tx < 0 || tx >= n || ty < 0 ||ty >= m || temp.t + 1 >= t)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = 1;
if(str[tx][ty] == 'x')
{
f.t = temp.t + 2;
}
else
{
f.t = temp.t + 1;
}
f.x = tx;
f.y = ty;
q.push(f);
}
}
}
if(t != maxx)
{
return true;
}
return false;
}
int main(int argc, char *argv[])
{
while(cin >> n >> m)
{
t = maxx;
num = 0;
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; i++)
{
cin >> str[i];
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(str[i][j] == 'a')
{
ex = i;
ey = j;
str[i][j] = '.';
}
if(str[i][j] == 'r')
{
sx = i;
sy = j;
s[num].x = i;
s[num++].y = j;
}
}
}
bfs();
if(t == maxx)
{
cout << "Poor ANGEL has to stay in the prison all his life." <<endl;
}
else
cout << t << endl;
}
return 0;
}
S题:
广搜的记录路径,深搜过不去。
# include <iostream>
# include <queue>
# include <cstring>
# include <algorithm>
# include <string>
using namespace std;
const int maxn = 105;
const int maxx = 0x3f3f3f3f;
bool vis[maxn][maxn];
char str[maxn][maxn];
int n, m, t,sx, sy, ex,ey;
int dis[][2] = {0, 1, 0, -1, 1, 0, -1, 0};//E W S N
int arr[maxn];
string st;
char ss[4] = {'E', 'W', 'S', 'N'};
# if 01
struct node
{
int x, y;
int t;
string str;
}s[maxn];
bool bfs()
{
queue<node> q;
struct node temp, front;
front.x = sx;
front.y = sy;
front.t = 0;
q.push(front);
while(!q.empty())
{
temp = q.front();
q.pop();
if(temp.x == ex && temp.y == ey && temp.t < t)
{
t = temp.t;
st = temp.str;
// cout <<temp.str << endl;
}
for(int i = 0; i < 4; i++)
{
int tx = temp.x + dis[i][0];
int ty = temp.y + dis[i][1];
if(str[tx][ty] == '#' || tx < 0 || tx >= n || ty < 0 ||ty >= m || temp.t + 1 >= t)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = true;
front.x = tx;
front.y = ty;
front.t = temp.t + 1;
front.str = temp.str + ss[i];
// cout << "tx = " << tx << "-- ty = " << ty << " "<< front.str << " ---" << ss[i]<< endl;
q.push(front);
}
}
}
if(t != maxx)
{
return true;
}
return false;
}
# endif
# if 0
void dfs(int x, int y, int z)
{
if(z >= t)
{
return ;
}
if(x == ex && y == ey && z < t)
{
t = z;
for(int i = 0; i < z; i++)
{
arr[i] = brr[i];
}
}
for(int i = 0; i < 4; i++)
{
int tx = x + dis[i][0];
int ty = y + dis[i][1];
if(str[tx][ty] == '#' || tx < 0 || tx >= n || ty < 0 ||ty >= m || z + 1 > t || vis[tx][ty])
{
continue;
}
vis[tx][ty] = true;
brr[z] = i;
dfs(tx, ty, z + 1);
vis[tx][ty] = false;
}
}
# endif
int main(int argc, char *argv[])
{
while(cin >> n >> m)
{
t = maxx;
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; i++)
{
cin >> str[i];
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(str[i][j] == 'E')
{
ex = i;
ey = j;
str[i][j] = '.';
}
if(str[i][j] == 'S')
{
sx = i;
sy = j;
}
}
}
bfs();
if(t != maxx)
cout << st<<endl;
else
{
cout << "Can't eat it!" <<endl;
}
}
return 0;
}
T题:
遇到相同的阵然后找一下转移一下
# include <iostream>
# include <queue>
# include <cstring>
# include <algorithm>
# include <string>
using namespace std;
const int maxn = 105;
const int maxx = 0x3f3f3f3f;
bool vis[maxn][maxn];
char str[maxn][maxn];
int n, m, t,sx, sy, ex,ey,dx,dy;
int dis[][2] = {0, 1, 0, -1, 1, 0, -1, 0};//E W S N
int arr[maxn];
int k;
string st;
char ss[4] = {'E', 'W', 'S', 'N'};
# if 01
struct node
{
int x, y;
int t;
}s[maxn];
bool f(char ch, int x,int y)
{
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if((i != x || y != j))
{
// cout << "i = " << i<< " j = " << j << endl;
if(str[i][j] == ch )
{
dx = i,dy = j;
return true;
}
}
}
}
return false;
}
bool bfs()
{
queue<node> q;
struct node temp, front;
front.x = sx;
front.y = sy;
front.t = 0;
q.push(front);
while(!q.empty())
{
temp = q.front();
q.pop();
// cout << "temp.x = " << temp.x << "--- temp.y = " << temp.y << endl;
if(temp.x == ex && temp.y == ey && temp.t < t)
{
t = temp.t;
// cout <<temp.str << endl;
}
for(int i = 0; i < 4; i++)
{
int tx = temp.x + dis[i][0];
int ty = temp.y + dis[i][1];
if(str[tx][ty] == '#' || tx < 0 || tx >= n || ty < 0 ||ty >= m || temp.t + 1 >= t)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = true;
if(str[tx][ty] >= 'a' && str[tx][ty] <= 'z')
{
// cout << "tx = " << tx << " ty = " << ty << " "<< str[tx][ty]<< endl;
if(f(str[tx][ty], tx, ty))
{
front.x = dx;
front.y = dy;
// cout << "dx = " << dx << " dy = " << dy << endl;
}
else
{
// cout << "false" << endl;
front.x = tx;
front.y = ty;
}
}
else
{
front.x = tx;
front.y = ty;
}
front.t = temp.t + 1;
q.push(front);
}
}
}
if(t != maxx)
{
return true;
}
return false;
}
# endif
int main(int argc, char *argv[])
{
int k;
while(cin >> k)
{
while(k--)
{
cin >> n >> m;
{
t = maxx;
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; i++)
{
cin >> str[i];
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(str[i][j] == 'Q')
{
ex = i;
ey = j;
str[i][j] = '.';
}
if(str[i][j] == 'L')
{
sx = i;
sy = j;
vis[sx][sy] = true;
}
}
}
bfs();
if(t != maxx)
cout << t<<endl;
else
{
cout << -1 <<endl;
}
}
}
}
return 0;
}
U题:
1.能量在食物网中的流动是单向的,所以保证了这个图是一个有向无环图。
2.在这个图中没有入度的点就是生产者(不止一个),没有出度并且不是生产者的点就是 最高级消费者。
有一个要注意的地方就是生产者在那里,没有人吃是不算一条食物链的。食物链的条数事实上就是从生产者到最高级消费者 的路径总数。
#include <cstdio>
#include <queue>
# include <iostream>
using namespace std;
const int MAXN = 2e5 + 7;
int n, m, ans, f[MAXN];
int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch > '9' || ch < '0') (ch == '-') && (f = -1), ch = getchar();
while (ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
struct Edge;
struct Node {
Edge *last;
int in, out, ma;
bool root;
} node[MAXN];
struct Edge {
Node *from, *to;
Edge *next;
Edge(Node *from, Node *to) : from(from), to(to), next(from->last) {}
};
void addE(int x, int y) {
node[x].last = new Edge(node + x, node + y);
node[x].out++;
node[y].in++;
}
queue<Node *> q;
int main() {
n = read();
m = read();
for (int i = 1; i <= n; i++) node[i].ma = i;
for (int i = 1; i <= m; i++) {
int x = read(), y = read();
addE(y, x);
}
for (int i = 1; i <= n; i++) {
if (!node[i].in && !node[i].out) continue;
if (!node[i].in) f[i] = 1, q.push(node + i);
if (!node[i].out && node[i].in) node[i].root = 1;
}
while (!q.empty()) {
Node *v = q.front();
q.pop();
for (Edge *e = v->last; e; e = e->next) {
f[e->to->ma] += f[v->ma];
e->to->in--;
if(!e->to->in) q.push(e->to);
}
}
for (int i = 1; i <= n; i++) {
if (node[i].root) ans += f[i];
}
printf("%d", ans);
return 0;
}
V题:
跟c题一样改变了一下加一个时间统计
# include <iostream>
# include <queue>
# include <cstring>
using namespace std;
const int maxn = 205;
bool vis[maxn][maxn];
char str[maxn][maxn];
int n, m, t,sx, sy, ex,ey;
int dis[][2] = {0, 1, 0, -1, 1, 0, -1, 0};
# if 0
struct node
{
int x, y, t;
};
bool bfs()
{
queue<struct node> q;
struct node temp, front;
front.x = sx;
front.y = sy;
front.t = 0;
q.push(front);
while(!q.empty())
{
temp = q.front();
q.pop();
if(temp.x == ex && temp.y == ey && temp.t <= t)
{
return true;
}
for(int i = 0; i < 4; i++)
{
int tx = temp.x + dis[i][0];
int ty = temp.y + dis[i][1];
if(str[tx][ty] != '.' || tx < 0 || tx >= n || ty < 0 ||ty >= m || temp.t + 1 > t)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = 1;
front.x = tx;
front.y = ty;
front.t = temp.t + 1;
q.push(front);
}
}
}
return false;
}
# endif
# if 01
bool flag;
int minn;
void dfs(int x, int y, int z)
{
if(flag)
{
return ;
}
if(x == ex && y == ey && z <= t)
{
flag = true;
return ;
}
for(int i = 0; i < 4; i++)
{
int tx = x + dis[i][0];
int ty = y + dis[i][1];
if(str[tx][ty] != '.' || tx < 0 || tx >= n || ty < 0 ||ty >= m || z > t)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = true;
dfs(tx, ty, z + 1);
vis[tx][ty] = false;
}
}
}
# endif
int main(int argc, char *argv[])
{
while(cin >> m >> n >> t, (m||n|| t))
{
flag = false;
minn = 0x3f3f3f3f;
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; i++)
{
cin >> str[i];
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(str[i][j] == 'S')
{
sx = i;
sy = j;
vis[i][j] = true;
}
if(str[i][j] == 'P')
{
str[i][j] = '.';
ex = i;
ey = j;
}
}
}
# if 0
if(bfs())
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
# endif
# if 01
dfs(sx, sy, 0);
if(flag)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
# endif
}
return 0;
}
W题:
记录转弯bfs(),dfs()都可以。
# include <iostream>
# include <queue>
# include <cstring>
using namespace std;
const int maxn = 105;
bool vis[maxn][maxn];
char str[maxn][maxn];
int n, m, t,sx, sy, ex,ey;
int dis[][2] = {0, 1, 0, -1, 1, 0, -1, 0};
# if 01
bool flag;
void dfs(int x, int y, int z, int sum)
{
if(flag)
{
return ;
}
if(x == ex && y == ey && sum <= t)
{
flag = true;
return ;
}
for(int i = 0; i < 4; i++)
{
int tx = x + dis[i][0];
int ty = y + dis[i][1];
if(str[tx][ty] != '.' || tx < 0 || tx >= n || ty < 0 ||ty >= m || sum > t)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = true;
if(z == -1 || z == i)
{
dfs(tx, ty, i, sum);
}
else if(z != i)
{
dfs(tx, ty, i, sum + 1);
}
vis[tx][ty] = false;
}
}
}
# endif
int main(int argc, char *argv[])
{
int k;
while(cin >> k)
{
while(k--)
{
cin >> n>> m >> t;
{
# if 01
flag = false;
# endif
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; i++)
{
cin >> str[i];
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(str[i][j] == 'S')
{
sx = i;
sy = j;
}
if(str[i][j] == 'P')
{
str[i][j] = '.';
ex = i;
ey = j;
}
}
}
# if 01
dfs(sx, sy, -1, 0);
if(flag)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
# endif
}
}
}
return 0;
}
X题:
跟前面的R题一样,除了需要注意这次的r是有多个
# include <iostream>
# include <queue>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxn = 205;
const int maxx = 0x3f3f3f3f;
bool vis[maxn][maxn];
char str[maxn][maxn];
int n, m, t,sx, sy, ex,ey;
int dis[][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int num;
# if 01
struct node
{
int x, y, t;
}s[maxn];
bool operator<(const node a, const node b)
{
return a.t > b.t;
}
bool bfs()
{
priority_queue<node> q;
struct node temp, f;
for(int i = 0; i < num; i++)
{
f.x = s[i].x;
f.y = s[i].y;
f.t = 0;
q.push(f);
}
while(!q.empty())
{
temp = q.top();
q.pop();
if(temp.x == ex && temp.y == ey && temp.t < t)
{
t = temp.t;
}
for(int i = 0; i < 4; i++)
{
int tx = temp.x + dis[i][0];
int ty = temp.y + dis[i][1];
if(str[tx][ty] == '#' || tx < 0 || tx >= n || ty < 0 ||ty >= m || temp.t + 1 >= t)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = 1;
if(str[tx][ty] == 'x')
{
f.t = temp.t + 2;
}
else
{
f.t = temp.t + 1;
}
f.x = tx;
f.y = ty;
q.push(f);
}
}
}
if(t != maxx)
{
return true;
}
return false;
}
# endif
int main(int argc, char *argv[])
{
while(cin >> n >> m)
{
t = maxx;
num = 0;
memset(vis, false, sizeof(vis));
for(int i = 0; i < n; i++)
{
cin >> str[i];
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(str[i][j] == 'a')
{
ex = i;
ey = j;
str[i][j] = '.';
}
if(str[i][j] == 'r')
{
sx = i;
sy = j;
s[num].x = i;
s[num++].y = j;
}
}
}
bfs();
if(t == maxx)
{
cout << "Poor ANGEL has to stay in the prison all her life." <<endl;
}
else
cout << t << endl;
}
return 0;
}
Y题:
预处理一下狗有多条然后入队就行
# include <iostream>
# include <queue>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxn = 205;
const int maxx = 0x3f3f3f3f;
bool vis[maxn][maxn];
char str[maxn][maxn];
int n, m, t,sx, sy, ex,ey;
int dis[][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int num;
int c;
struct node
{
int x, y;
}s[maxn];
bool bfs()
{
queue<node> q;
struct node temp, f;
for(int i = 0; i < num; i++)
{
f.x = s[i].x;
f.y = s[i].y;
q.push(f);
}
while(!q.empty())
{
temp = q.front();
q.pop();
if(str[temp.x][temp.y] == 'p' )
{
c++;
}
for(int i = 0; i < 4; i++)
{
int tx = temp.x + dis[i][0];
int ty = temp.y + dis[i][1];
if(str[tx][ty] == '#' || tx < 0 || tx >= n || ty < 0 ||ty >= m)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = 1;
f.x = tx;
f.y = ty;
q.push(f);
}
}
}
if(t != maxx)
{
return true;
}
return false;
}
int main(int argc, char *argv[])
{
while(cin >> n >> m, (m||n))
{
t = maxx;
num = 0;
memset(vis, false, sizeof(vis));
c = 0;
for(int i = 0; i < n; i++)
{
cin >> str[i];
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
if(str[i][j] == 'd')//搜救犬
{
sx = i;
sy = j;
s[num].x = i;
s[num++].y = j;
}
}
}
bfs();
cout << c << endl;
}
return 0;
}
Z题:
让你输出广搜各个点到目标点的步数
# include <queue>
# include <cstring>
# include <algorithm>
using namespace std;
const int maxn = 205;
const int maxx = 0x3f3f3f3f;
bool vis[maxn][maxn];
int str[maxn][maxn];
int n, m, t,sx, sy, ex,ey;
int dis[][2] = {0, -1, 0, 1, 1, 0, -1, 0};
int num;
int c;
struct node
{
int x, y, t;
};
bool bfs()
{
queue<node> q;
struct node temp, f;
f.x = sx;
f.y = sy;
f.t = 0;
q.push(f);
while(!q.empty())
{
temp = q.front();
q.pop();
for(int i = 0; i < 4; i++)
{
int tx = temp.x + dis[i][0];
int ty = temp.y + dis[i][1];
if( tx < 1 || tx > n || ty < 1 ||ty > m)
{
continue;
}
if(!vis[tx][ty])
{
vis[tx][ty] = 1;
f.x = tx;
f.y = ty;
f.t = temp.t + 1;
q.push(f);
str[tx][ty]= f.t;
// cout << "tx = " << tx << " ty = " << ty << " t = " << f.t <<endl;
}
}
}
}
int main(int argc, char *argv[])
{
while(cin >> n >> m >> sx >> sy)
{
memset(vis, false, sizeof(vis));
memset(str, false, sizeof(str));
vis[sx][sy] = true;
bfs();
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
cout << str[i][j];
}
cout << endl;
}
}
return 0;
}