vis

最短路总结

坚强是说给别人听的谎言 提交于 2020-01-25 16:18:24
这一段时间复习了一下最短路,做了几道非常典型特别考察最短路性质的题 1.P1144 最短路计数 这个题主要考察对松弛操作的理解。 关键代码 if(dis[v] > dis[u] + 1) { dis[v] = dis[u] + 1; ans[v] = ans[u]; q.push(make_pair(dis[v],v)); } else if(dis[v] == dis[u] + 1) { ans[v] += ans[u]; ans[v] %= mo; } 2.CF786B Legacy 线段树优化建边,对于一个点,与一个连续区间里的点连边,可以利用线段树的特性来降低连边复杂度。 void build1(int &p,int l,int r) { if(l==r) { p=l;return; } p=++tot; int mid=l+r>>1; build1(lc[p],l,mid); build1(rc[p],mid+1,r); add(p,lc[p],0);add(p,rc[p],0); } 3.P1772 [ZJOI2006]物流运输 这是一道DP加最短路的题目,由于数据很小,我们的复杂度可以很高 设计这样的一个DP。f[i] 表示前i天的花费,考虑转移,考虑第j天是否改变航线 方程为:f[i] = min(f[i],f[j-1] + (i-j+1) * x + k);

迷宫问题

浪子不回头ぞ 提交于 2020-01-25 15:24:08
之前写的东西因为断网没了(心态爆炸。。。) 总之用宽搜解决迷宫问题就是用队列先进先出的特点,一旦找到了结果一定是最短的(结合树状图自己理解) 代码如下 #include <iostream> #include <queue> #include <algorithm> #include <cstring> #include <cstdio> #include <cstdio> using namespace std; bool vis[45][45]; char map[45][45]; int n, m; struct node{ int x, y, step; //横纵坐标、到这个格子走了多少步 }; bool isok(int x, int y) { if (x >= 0 && x < n && y >= 0 && y < n && !vis[x][y]) return 1; return 0; } int main() { while(scanf("%d%d",&n, &m) != EOF) { for (int i = 0; i < n; ++i) scanf("%s", map[i]); //绘制地图 memset(vis, 0, sizeof(vis)); for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j)

题解 P6005 【[USACO20JAN]Time is Mooney G】

不羁岁月 提交于 2020-01-25 01:39:20
抢第一篇题解 这题的思路其实就是一个非常简单的dijkstra,如果跑到第一个点的数据不能更新的时候就输出 很多人不知道要跑多少次才停.其实这题因为答案要减去 T*c^2,而每条边的值 <= 1000,稍微推一下就可以发现这个程序最多跑1000次. 所以,简单暴力的做法就是暴力写1000次dijkstra (01dij或者二维1000*1000都可以).这个方法当然可以优化, 但是没有超时谁理他呢 现在剩下一个小问题(如果没有经过的点,我们不能更新连同他的路).那么怎么办呢? 摆在眼前的路有两条.第一:到所有点的初始值设成-1跑.如果目前的点的值为-1就证明他没有被经过,所以需要跳过 第二:做一个vis,记录每次经过并且以前没有经过过的点.这里我用的是queue,记录所有这一次被拿到的点. 注意不要马上更新,因为如果你马上更新就会出现没有经过的点被更新了 01的意义就是保证所有点更新的都是之前更新过但这一次没有更新的,保证不会出现一条边被更新很多次的情况 话不多说,上代码 #include <iostream> #include <algorithm> #include <math.h> #include <queue> using namespace std; int dp[1005][2],head[100005],tot = 0,n,m,c, cost[1005],ans=0

马的移动

懵懂的女人 提交于 2020-01-24 07:11:18
马的移动 题目描述 小明很喜欢下国际象棋,一天,他拿着国际象棋中的“马”时突然想到一个问题: 给定两个棋盘上的方格a和b,马从a跳到b最少需要多少步? 现请你编程解决这个问题。 提示:国际象棋棋盘为8格*8格,马的走子规则为,每步棋先横走或直走一格,然后再往外斜走一格。 输入 输入由两个方格组成,每个方格包含一个小写字母(a~h),表示棋盘的列号,和一个整数(1~8),表示棋盘的行号。 输出 输出一行"xx->yy:n”。 样例输入 e2 e4 样例输出 e2->e4:2 题解: 因为求最少步数,所以用bfs。 代码: #include<bits/stdc++.h> #define MAXN 8 using namespace std; struct Node { int x,y; int step; }; queue<Node> Q; int vis[MAXN][MAXN]; char str1[10],str2[10]; int bx,by,ex,ey,ans; int zb[8][2] = {-1,-2,-2,-1,-2,1,-1,2,1,2,2,1,2,-1,1,-2}; void bfs() { Node tmp,nt; tmp.x = bx; tmp.y = by; tmp.step = 0; vis[bx][by] = 1; Q.push(tmp); while(!Q

数据结构与算法——前缀树和贪心算法(2)

痴心易碎 提交于 2020-01-23 17:12:09
数的划分 将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。 例如:n=7,k=3,下面三种分法被认为是相同的。1,1,5; 1,5,1; 5,1,1; 问有多少种不同的分法。 输入:n,k ( 6 < n ≤ 200,2 ≤ k ≤ 6 ) 输出:一个整数,即不同的分法。 示例1 输入 //两个整数 n,k ( 6 < n ≤ 200, 2 ≤ k ≤ 6 ) 7 3 输出 //1个整数,即不同的分法。 4 C++ 法一:记忆化搜索 方法为减而治之,把n划分成k份的答案就相当于每次把n分成a,b两个数,再把a分成k-1份,然后把每次a分成k-1份的答案相加即可。注意点是每轮分出来的b要不大于上一轮分出来的b。 //https://www.nowcoder.com/questionTerminal/3773e51c48ec4727939cc85a8bc4c60d #include <bits/stdc++.h> using namespace std; #define rep(i,n) for (int i = 0; i < (n); ++i) #define For(i,s,t) for (int i = (s); i <= (t); ++i) #define rFor(i,t,s) for (int i = (t); i >= (s); --i) #define

网络流

早过忘川 提交于 2020-01-22 21:05:39
一个网络 \(G=(V,E)\) 是一张有向图,图中每条有向边 \((x,y)\in E\) 都有一个给定的权值 \(c(x,y)\) ,称为边的容量。特别地,若 \((x,y) \notin E\) ,则 \(c(x,y)=0\) 。图中还有两个指定的特殊节点 \(S,T \in V(S \neq T)\) 分别被称为源点和汇点。 设 \(f(x,y)\) 是定义在节点二元组 \((x \in V,y \in V)\) 上的实数函数,且满足: 容量限制: \(f(x,y) \leq c(x,y)\) 斜对称: \(f(x,y)=-f(y,x)\) 流量守恒: \(\forall x \neq S,\ x \neq T,\ \sum_{(u,x)\ \in E} f(u,x) = \sum_{(x,v)\ \in E}f(x,v)\) \(f\) 称为网络的流函数,对于 \((x,y) \in E\) , \(f(x,y)\) 称为边的流量, \(c(x,y)-f(x,y)\) 称为边的剩余流量 \(\sum_{(S,v)\ \in E} f(S,v)\) 称为整个网络的流量( \(S\) 为源点) 最大流 Edmond—Karp算法 若一条从源点 \(S\) 到汇点 \(T\) 的路径上各条边的剩余容量都大于 \(0\) ,则称这条路径为一条增广路 \(EK\) 算法为用 \

棋盘问题 题解

ぃ、小莉子 提交于 2020-01-22 15:24:23
棋盘问题 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。 Input输入含有多组测试数据。 每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n 当为-1 -1时表示输入结束。 随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。 Output对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。 Sample Input 2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1 Sample Output 2 1 DFS搜索法 #include<iostream> #include<queue> #include<stdio.h> #include<string.h> #include<string> #define N 10 using namespace std; int n,k,ans,cnt;//ans 方案数,cnt 棋子数 string mp[N];//string 定义字符串 bool vis[N];

PTA练习题 1003 Emergency (25分) 【dfs最短路】

狂风中的少年 提交于 2020-01-22 03:32:28
传送门:1003 1003 Emergency (25分) As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible. Input Specification: Each input file contains one test case. For each test case, the first line contains 4

NEKO's Maze Game-cf

佐手、 提交于 2020-01-21 23:12:16
   题意: 给你一个2×n的矩阵,起点在左上,终点在右下,可以移动到本格相邻的格子里,给你q个时间点,每个时间点会有一个格子的状态发生变化,格子状态分为可走和不可走,一开始所以格子都是可走的,要求输出每个时间点能不能从起点走到终点。    思路: 对任意格子来说,设它的坐标为x,y,对于他的另一行的三个坐标3-x,y-1 ,3-x,y和3-x,y+1有一个是不可走的,整个道路就被塞死了,就无法从起点走到终点。也就是说整个矩阵任意一个点满足这种关系,整条路走不通,所以我们统计整个矩阵有多少组这种关系设为num,对于每个时间点,如果它是让格子解除封印,就将num减去它能减少的组数,相对应封禁格子就是让num加,在每一个时间点判断一下num是不是为0就行了。    ac代码: #include<iostream> using namespace std; const int maxn=1e5+10; int n,q; int vis[3][maxn]; int ans[maxn];//0可以,1不行 int check(int x,int y){ int h=3-x; if(y==1){ return vis[h][y]+vis[h][y+1]; } else if(y==n){ return vis[h][y-1]+vis[h][y]; } else return vis[h][y

洛谷P2697宝石串

一世执手 提交于 2020-01-21 10:51:24
前缀和+字符串处理即可 不懂DP者的福利 #include <bits/stdc++.h> using namespace std; int vis[100011999]; signed main() { //稍微优化下 ios::sync_with_stdio(0); //稍微优化下,真正赛场上还是建议scanf的 int sum = 10000000; int ans = 0; char x; int i = 1; while(cin>>x) { if(x=='G') { sum++; } else if(x=='R'){ sum--; } if(sum==10000000) { //没发生变化(平衡) ans=i; } else if(vis[sum]==0) { vis[sum] = i; //记录结果 } else { ans = max(ans,i-vis[sum]); //计算答案 } i++; } std::cout<<ans<<endl; } 来源: https://www.cnblogs.com/littlefrog/p/12220829.html