记录一个菜逼的成长。。
PS:因为备战省赛,并没有什么难的算法和数据结构。。
A:HDU2181 哈密顿绕行世界问题
简单的dfs,每个城市只有三条边直接搜索即可。
#include <bits/stdc++.h>
using namespace std;
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define pb push_back
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 20 + 10;
int g[maxn][maxn],vis[maxn];
int ans[maxn],cas = 1;
void dfs(int st,int x,int cnt)
{
if(cnt == 20){
if(g[x][st]){
printf("%d: ",cas++);
for( int i = 1; i < 20; i++ ){
printf(" %d",ans[i]);
}
printf(" %d %d\n",x,st);
}
}
vis[x] = 1;
ans[cnt] = x;
for( int i = 1; i <= 20; i++ ){
if(!vis[i] && g[x][i]){
dfs(st,i,cnt+1);
}
}
vis[x] = 0;
}
int main()
{
for( int i = 1; i <= 20; i++ ){
int x;
for( int j = 0; j < 3; j++ ){
scanf("%d",&x);
g[i][x] = 1;
}
}
int m;
while(~scanf("%d",&m) , m != 0){
cl(vis,0);cas = 1;
dfs(m,m,1);
}
return 0;
}
B:HDU2102 A计划
基础的三维bfs,求最短路径。
只是这里有个坑,两层相对的位置都是 ‘#’,还有每次传送的时候,记得把步数也记录就可以了。
#include <bits/stdc++.h>
using namespace std;
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define pb push_back
typedef long long LL;
const int INF = 0x3f3f3f3f;
char g[5][20][20];
int vis[5][20][20],n,m,T;
int dx[] = {-1,0,1,0},dy[] = {0,1,0,-1};
struct Node{
int x,y,z;
Node(){}
Node(int xx,int yy,int zz):x(xx),y(yy),z(zz){}
};
void bfs(int x,int y,int z)
{
cl(vis,0);
queue<Node>q;
q.push(Node(x,y,z));
vis[z][x][y] = 1;
int cnt = 1,d = 2,tmp = 0;
while(!q.empty()){
Node f = q.front();q.pop();
if(g[f.z][f.x][f.y] == '#')f.z = f.z ^ 1,vis[f.z][f.x][f.y] = vis[f.z^1][f.x][f.y];
if(cnt)cnt--;
if(g[f.z][f.x][f.y] != '*' && g[f.z][f.x][f.y] != '#'){
for( int i = 0; i < 4; i++ ){
int nx = f.x + dx[i],ny = f.y + dy[i],nz = f.z;
if(nx < 0 || nx >= n || ny < 0 | ny >= m)continue;
if(vis[nz][nx][ny] || g[nz][nx][ny] == '*')continue;
vis[nz][nx][ny] = d;
q.push(Node(nx,ny,nz));
tmp++;
}
}
if(!cnt){cnt = tmp,tmp = 0,d++;}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&T);
int tx,ty,tz;
for( int i = 0; i < 2; i++ ){
for( int j = 0; j < n; j++ ){
scanf("%s",g[i][j]);
for( int k = 0; k < m; k++ ){
if(g[i][j][k] == 'P')tx = j,ty = k,tz = i;
}
}
}
bfs(0,0,0);
if(!vis[tz][tx][ty]){
puts("NO");
}
else {
if(vis[tz][tx][ty] - 1 <= T)puts("YES");
else puts("NO");
}
}
return 0;
}
C:HDU5695 Gym Class
依据题目意思很容易想到拓扑排序。
只是多了个条件,每次要找到前面最大的,使得最后结果最大。那么贪心一下,每次入度为0的点,使值大的先输出即可。可用优先队列替换掉原先的队列来维护。
#include <bits/stdc++.h>
using namespace std;
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define pb push_back
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 100000 + 10;
vector<int>g[maxn];
int d[maxn],n,m;
LL topsort()
{
priority_queue<int>q;
for( int i = 1; i <= n; i++ ){
if(!d[i])q.push(i);
}
LL ans = 0;
int mn = INF;
while(!q.empty()){
int t = q.top();q.pop();
mn = min(mn,t);
ans += mn;
for( int i = 0; i < g[t].size(); i++ ){
d[g[t][i]] --;
if(!d[g[t][i]]){
q.push(g[t][i]);
}
}
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
cl(d,0);
for( int i = 1; i <= n; i++ )g[i].clr;
while(m--){
int u,v;
scanf("%d%d",&u,&v);
g[u].pb(v);
d[v]++;
}
printf("%lld\n",topsort());
}
return 0;
}
D:HDU5690 All X
F(x,m)modk=c
F(x,m)=10m−19∗x
.
原式就转换为
10m−19∗xmodk=c
但是我们不能保证
9
跟
所以转换为
(10m−1)∗xmod9k=9c
如果互质则可以转换为
(10m−1)∗xmodk=9c
那么直接快速幂计算即可。
#include <bits/stdc++.h>
using namespace std;
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define pb push_back
typedef long long LL;
const int INF = 0x3f3f3f3f;
LL Power(LL a,LL b,LL c)
{
LL ret = 1;
while(b){
if(b&1)ret = (ret * a) % c;
b >>= 1;
a = (a * a) % c;
}
return ret;
}
int main()
{
int T,cas = 1;
scanf("%d",&T);
while(T--){
int x,k,c;
LL m;
scanf("%d%lld%d%d",&x,&m,&k,&c);
k *= 9;
c *= 9;
LL ret = Power(10,m,k);
ret = ((ret-1) * x) % k;
printf("Case #%d:\n%s\n",cas++,ret == c ? "Yes" : "No");
}
return 0;
}
E:见这里
F:见这里

本文解析了四个ACM竞赛中的经典算法题,包括哈密顿绕行世界问题的DFS算法、三维迷宫最短路径的BFS算法、GymClass问题的拓扑排序改进算法以及AllX问题的快速幂计算技巧。
2198

被折叠的 条评论
为什么被折叠?



