7-1 最佳调度问题
#include<iostream>
#include<algorithm>
using namespace std;
int n,k,t[99],ans[99],min_time=0x3f3f3f3f;
void dfs(int level)
{
if(level==n)
{int tmp=*max_element(ans,ans+n);if(tmp<min_time) min_time=tmp;return;
}
for(int i=0;i<k;i++)
{ans[i]+=t[level];if(ans[i]<min_time) dfs(level+1);ans[i]-=t[level];
}
}
int main()
{
cin>>n>>k;
fill(ans,ans+99,0);
for(int i=0;i<n;i++)
cin>>t[i];
dfs(0);
cout<<min_time<<endl;
}
7-2 代码排版
#include <bits/stdc++.h>
using namespace std;
int point, space = 2, mark, tp, cnt, use, temp;
string s;
int Function(int c) {
if (c == 0) while (s[point] == ' ') point++;
else if (c == 1) for (int i = 0; i < space; i++) cout << ' ';
else if (c == 2) {if (s.substr(point, 2) == "if" && (s[point + 2] == '(' || s[point + 2] == ' ')) return 2;else if (s.substr(point, 3) == "for" && (s[point + 3] == '(' || s[point + 3] == ' ')) return 3;else if (s.substr(point, 4) == "else" && (s[point + 4] == '(' || s[point + 4] == ' ')) return 4;else if (s.substr(point, 5) == "while" && (s[point + 5] == '(' || s[point + 5] == ' ')) return 5;
} else if (c == 3) {Function(0);if (Function(2) == 4) return 0;while (mark) {space -= 2;Function(1);cout << "}\n";mark--;}
}
return 0;
}
int main() {
getline(cin, s);
Function(0);
for (int i = point; s[i] != ')'; i++) cout << s[i];
cout << ")\n{\n";
point = s.find('{') + 1;
while (1) {Function(0);temp = Function(2);if (s[point] == '{') {Function(1);cout << "{\n";space += 2;point++;} else if (s[point] == '}') {space -= 2;Function(1);cout << "}\n";if (space == 0) return 0;Function(3);point++;} else if (temp) {Function(1);cout << s.substr(point, temp);point += temp;if (temp != 4) {Function(0);tp = point;cnt = 0;while(tp < s.size()) {if (s[tp] == '(') cnt++;else if (s[tp] == ')') cnt--;tp++;if (cnt == 0) break;}cout << ' ' << s.substr(point, tp - point);point = tp;}cout << " {\n";space += 2;Function(0);if (s[point] != '{') {use = 1;mark++;} else {use = 0;point++;}} else {Function(1);cnt = s.find(';', point);cout << s.substr(point, cnt - point + 1) << '\n';point = cnt + 1;if (use && mark) {space -= 2;Function(1);cout << "}\n";mark--;Function(3);}}
}
return 0;
}
7-3 八皇后问题(*)
#include <bits/stdc++.h>const int maxn = 100 + 10;
using namespace std;int sum, n, cnt;
int C[maxn];
bool vis[3][maxn];
int Map[maxn][maxn];//打印解的数组//一般在回溯法中修改了辅助的全局变量,一定要及时把他们恢复原状
void Search(int cur) //逐行放置皇后
{cnt++;if (cur == n) {sum++;if (sum > 1)cout << '\n';for (int i = 0; i < cur; i++)Map[i][C[i]] = 1;//打印解for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (Map[i][j]) {cout << "Q";} elsecout << ".";if (j != n - 1) {cout << ' ';} else {cout << '\n';}}}memset(Map, 0, sizeof(Map)); //还原} elsefor (int i = 0; i < n; i++) //尝试在 cur行的 各 列 放置皇后{if (!vis[0][i] && !vis[1][cur + i] && !vis[2][cur - i + n]) //判断当前尝试的皇后的列、主对角线{vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = true;C[cur] = i;//cur 行的列是 iSearch(cur + 1);vis[0][i] = vis[1][cur + i] = vis[2][cur - i + n] = false;//切记!一定要改回来}}
}int main() {scanf("%d", &n);memset(vis, false, sizeof(vis));memset(Map, 0, sizeof(Map));sum = cnt = 0;Search(0);if (!sum) {cout << "None\n";}
// printf("%d %d\n",sum,cnt);//输出 解决方案 和 递归次数return 0;
}
7-4 0-1背包
#include <bits/stdc++.h>
using namespace std;
int n,c;
struct stru{
int weight,value;
}a[105];
bool cmp(const stru &x,const stru &y){
if(x.weight>y.weight) return true;
return false;
}
int main(){
cin>>n>>c;
int dp[1005]={0};
for(int i=0;i<n;i++){scanf("%d%d",&a[i].weight,&a[i].value);
}
sort(a,a+n,cmp);for(int i=0;i<n;i++){for(int j=c;j>=a[i].weight;j--){if(dp[j]<dp[j-a[i].weight]+a[i].value){dp[j]=dp[j-a[i].weight]+a[i].value;}}
}
cout<<dp[c]<<endl;
}
7-5 工作分配问题
#include<bits/stdc++.h>
using namespace std;
int num[101][101];
int book[101];
int mincost = 9999999;
int n;
void dfs(int i, int curcost) {
if (i > n) { // 寻找结束if (curcost < mincost) //判断是否比最小值小mincost = curcost;return; // 无论执行不执行if语句都要return因为寻找已经结束
}
for (int j = 1;j <= n;j++) {// 如何这个列还没有被访问并且当前工资加上num[i][j]// 小于mincost进行循环,因为大于的话就没必要找了。if (book[j] == 0 && curcost + num[i][j] < mincost) {book[j] = 1;curcost += num[i][j];dfs(i + 1, curcost);book[j] = 0; //进行回溯,因为要多次寻找确定最小值curcost -= num[i][j]; // 回溯时要减掉之前的值}
}
}
int main() {cin >> n;
for (int i = 1;i <= n;i++) {for (int j = 1;j <= n;j++) {cin >> num[i][j];}
}
dfs(1, 0); //进行深度搜素寻找最小工资
cout << mincost;
}
7-6 最佳组队问题
#include<bits/stdc++.h>
using namespace std;
int n;
int book[101];
int mp[101][101];
int maxsum = 0;
void show() {
for (int i = 1;i < 15;i++)book[i] = 0;
}
void dfs(int i, int cursum) {
if (i > n) {if (cursum > maxsum)maxsum = cursum;return;
}
for (int j = 1;j <= n;j++) {if (book[j] == 0 ) {book[j] = 1;dfs(i + 1, cursum + mp[i][j]);book[j] = 0;}
}
}
int main() {
while (cin >> n) {for (int i = 1;i <= n;i++) {for (int j = 1;j <= n;j++) {cin >> mp[i][j];}}show();maxsum = 0;dfs(1, 0);cout << maxsum<<endl;
}}
7-7 自然数拆分问题
#include<iostream>
#include<cstdio>
using namespace std;
int n,d[53]={1},m;
void dfs(int a){
for(int i=d[a-1];i<=m;i++){if(i == n) continue;d[a] = i;m-=i;if(m == 0){printf("%d=",n);for(int j = 1;j<a;j++)printf("%d+",d[j]);printf("%d\n",d[a]);}elsedfs(a+1);m+=i;
}
}
int main(){
cin>>n;
m = n;
dfs(1);
cout<<n<<"="<<n;
return 0;
}
7-8 整数拆分
#include <iostream>
#include <vector>
using namespace std;int n, num;
vector<int> v;void dfs(int k, int sum) {if(sum > n) return;if(sum == n) {cout << n << "=";for(int i = 0; i < v.size(); i++) {if(i) cout << "+";cout <<v[i];}cout << endl;num++;return;}for(int i = k; i < n; i++) {v.push_back(i);dfs(i, sum + i);v.pop_back();}
}int main() {
#ifndef ONLINE_JUDGEfreopen("in.txt","r", stdin);freopen("out.txt","w", stdout);
#endif // ONLINE_JUDGEcin >> n;dfs(1,0);cout <<num;return 0;
}
7-9 子集和问题
#include <iostream>
#include <vector>using namespace std;// 输出子集
void printSubset(const vector<int>& w, const vector<int>& subset) {for (int i = 0; i < subset.size(); ++i) {cout << subset[i] << " ";}cout << endl;
}// 递归方式求解子集和问题
void subsetSum(const vector<int>& w, vector<int>& subset, int index, int sum, int W) {if (sum == W) {printSubset(w, subset);return;}if (index == w.size() || sum > W) {return;}// 包含当前元素subset.push_back(w[index]);subsetSum(w, subset, index + 1, sum + w[index], W);// 不包含当前元素subset.pop_back();subsetSum(w, subset, index + 1, sum, W);
}int main() {int n, W;cin >> n >> W;vector<int> w(n);for (int i = 0; i < n; ++i) {cin >> w[i];}vector<int> subset;subsetSum(w, subset, 0, 0, W);return 0;
}
7-10 排列问题(*)
#include<stdio.h>
int m, n, ans[30], flag[30];//ans[]保存答案所选字母的序号,flag[]判断该字母是否被标记过
char s[30] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
void search(int cur){
if(cur == n){//输出一个排列 for(int i = 0; i < n; i++){printf("%c", s[ans[i]]);}printf("\n");
}
else{for(int k = 0; k < m; k++){//从m个字母中,每次选取一个未被标记过的,k每次从0开始判断,即可实现字典序排列 if(flag[k] == 0){//该字母未被标记时,进入下一层ans[cur] = k; //保存字母序号flag[k] = 1;search(cur + 1);flag[k] = 0;}}
}
}int main()
{
scanf("%d %d", &m, &n);search(0);return 0;
}
7-11 组合问题(*)
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;// 输出组合
void printCombinations(const vector<char>& letters, const vector<int>& combination) {for (int index : combination) {cout << letters[index];}cout << endl;
}// 递归方式求解组合问题
void generateCombinations(const vector<char>& letters, vector<int>& combination, int index, int n, int start) {if (index == n) {printCombinations(letters, combination);return;}for (int i = start; i < letters.size(); ++i) {combination[index] = i;generateCombinations(letters, combination, index + 1, n, i + 1);}
}int main() {int m, n;cin >> m >> n;vector<char> letters(m);for (int i = 0; i < m; ++i) {letters[i] = 'A' + i;}vector<int> combination(n);generateCombinations(letters, combination, 0, n, 0);return 0;
}
7-12 666
#include<iostream>
#include<vector>
using namespace std;
int n,m;
vector < vector <int> >arr;
int num;
int total;
int next_w[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
void dfs(int q,int x,int y,int pre_x,int pre_y){
if(arr[x][y]>=6){if(q==3){num++;total++;return ;}int next_x,next_y;for(int i=0;i<4;i++){next_x=x+next_w[i][0];next_y=y+next_w[i][1];if((next_y!=pre_y||next_x!=pre_x)&&next_x>0&&next_x<=n&&next_y>0&&next_y<=m){dfs(q+1,next_x,next_y,x,y);}}
}
}
int main(){
cin>>n>>m;
arr.resize(n+2);
for(int i=0;i<=n+1;i++){arr[i].resize(m+2);
}
for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>arr[i][j];}
}
for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){num=0;dfs(1,i,j,0,0);cout<<num;if(j!=m)cout<<' ';}cout<<endl;
}
cout<<total<<endl;
return 0;
}
7-13 比赛的配对分配
#include<bits/stdc++.h>
using namespace std;
int main()
{int res = 0;int n;cin>>n;while(n!=1){res += n/2;n = n % 2 == 0 ? n / 2 : n / 2 + 1;}cout<< res;}
7-14 回文串的切割
#include<bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
bool judge(string str)
{string copy_str = str;reverse(str.begin(),str.end());return str == copy_str;
}long long dfs(string str)
{if (str.size() <= 1) return 1;long long ans = 0;for (int i = 0; i < str.size(); ++i){if (judge(str.substr(0, i + 1))){ans = ans + dfs(str.substr(i+1)) % MOD;ans = ans % MOD;}}return ans;
}
int main()
{string s;getline(cin, s);if (s.empty()) cout << 0 << endl;elsecout << dfs(s);return 0;
}
7-15 有重复元素的全排列
#include <iostream>
#include <vector>
#include <set>using namespace std;class Solution {
public:int factorial(int n) {if (n == 0 || n == 1) return 1;return n * factorial(n - 1);}void permuteUnique(vector<int>& nums, int start, set<vector<int>>& result) {if (start == nums.size()) {result.insert(nums);return;}for (int i = start; i < nums.size(); ++i) {swap(nums[start], nums[i]);permuteUnique(nums, start + 1, result);swap(nums[start], nums[i]);}}int countPermutations(vector<int>& nums) {int n = nums.size();set<vector<int>> result;permuteUnique(nums, 0, result);return result.size();}
};int main() {int n;cin >> n;vector<int> nums(n);for (int i = 0; i < n; ++i) {cin >> nums[i];}Solution solution;cout << solution.countPermutations(nums) << endl;return 0;
}
7-16 批处理作业调度
#include<bits/stdc++.h>
using namespace std;vector<vector<int> > ans;
vector<int> path;void backtacking(int n,vector<bool> &v) {//递归终止的条件 if(path.size() == n){ans.push_back(path);return;}for(int i = 1; i <= n; i++) {if(v[i] == true) continue;v[i] = true;path.push_back(i);backtacking(n,v);//这里的level+1代表的是我们每次的遍历范围在变小 path.pop_back();//当我们得到一种可行解的时候,因为我们要回溯求取其他的解,所以清理最后装进容器的元素 v[i] = false;}
}int main(){int N;vector<int>v1(100),v2(100); vector<bool> v3(100,false);vector<int>v4;//记录最后每种排列的所求时间和 cin >> N;for (int i = 1; i <= N; i++) { cin >> v1[i];}for (int i = 1; i <= N; i++) {cin >> v2[i];} //cout << v1[1] << ' ' << v1[2] << ' ' << v1[3];backtacking(N,v3);//cout << endl;for (int i = 0; i < ans.size(); i++) {int sumTime1 = 0;int sumTime2 = 0; int sumTime3 = 0;//记录一种排列最后的完成总时间 for (int j = 0; j < N; j++){//cout << ans[i][j] << ' ';// 1 2 3int index = ans[i][j];sumTime1 += v1[index];//这里计算在机器1上的完成时间 sumTime2 = sumTime1; //因为在机器二上的完成时间需要在机器1上完成后才可记录 sumTime2 += v2[index];//这里记录在机器2上的完成时间 sumTime3 += sumTime2;//记录所有作业的完成时间和 }v4.push_back(sumTime3);} sort(v4.begin(),v4.end());cout << v4[0];
}
7-17 旅行售货员
#include<bits/stdc++.h>
using namespace std;int INF=999999999;
const int N=100; //const 初始化
int maps[N][N]; //存储图
int n,m; //n表示顶点数,m表示边数
int bestw;struct Node
{
int x[N]; //解向量,方便从1开始,记录路径
int cl; //表示当前已走过的路径长度
int id; //表示层数
};//重写 优先队列当中排序方法 按每次路径最短的升序处理
bool operator<(const Node &a,const Node &b){
return a.cl>b.cl;
}void bfs()
{
priority_queue<Node>q; Node node;node.cl = 0; // 0 表示当前已经的走的路径长度,2表示层数node.id = 2;//表示的是每个结点的序号,用于记录树当中路径
for(int i=1;i<=n;i++){node.x[i]=i;
}q.push(node);while(!q.empty()){//这个新结点的信息就是上方的node,其解向量为 1,2,3,4...而c = 0 id = 2; Node newnode=q.top();q.pop();int t;t = newnode.id;//当前层数if(t==n){//当n==4的时候,其实是走了3个结点两个距离,所以还需要判断与最后一个结点//的距离,以及最后一个结点和首节点的距离。//如果两个结点中有一个的距离是无穷的那么,它的路径长度肯定不满足要求 if(maps[newnode.x[t-1]][newnode.x[n]] != INF && maps[newnode.x[n]][newnode.x[1]] != INF ){//如果满足要求的话,那么就要判断已有的路径长度+到最后一个结点长度//+最后一个结点到源结点的距离。 if(newnode.cl + maps[newnode.x[t-1]][newnode.x[n]]+ maps[newnode.x[n]][newnode.x[1]] < bestw){bestw = newnode.cl+maps[newnode.x[t-1]][newnode.x[n]]+ maps[newnode.x[n]][newnode.x[1]];//更新bestw;} else{//如果我们已经知道其最后的总路程是大于bestw的话,那就没有必要再统计其邻接点了 continue;}}else{//这里也是,如果我们已经知道其到达最后一个结点,或是最后一个结点到达首结点//的距离是无穷的,那么我们就没必要再往下统计了 continue;} } if(newnode.cl >= bestw) continue;//限界条件//拿出队列当中的头节点,扩展其所有的分支 for(int j = t; j <= n; j++){//扩展所有分支//这里是将当前的结点的临界点遍历,但是需要比较已有的路径//长度跟当前的最优值,比其小才遍历,否则的话,再往下进行肯定是比最优值大的 //因为结点层数是比矩阵当中记录的行数多1,所以要减去。 if(newnode.cl + maps[newnode.x[t-1]][newnode.x[j]] < bestw){int c = newnode.cl + maps[newnode.x[t-1]][newnode.x[j]];//生成一个新的结点 且更新现在的路径长度和遍历的树的层数 Node node;node.cl = c;node.id = t+1;//复制父节点的解向量 for(int i = 1; i <= n; i++)node.x[i] = newnode.x[i];//这个交换是为了 扩展结点可以在下一次的加入邻接点(活结点)的时候 //可以正确统计该活结点在矩阵当中的正确行数 swap(node.x[t],node.x[j]);q.push(node);}}
}}
int main(){cin>>n;
for(int i=1;i<=n;i++){for(int j = 1; j <= n; j++) {int w;cin >> w;if(w == 0)maps[i][j] = INF;elsemaps[i][j] = w; }}
bestw=INF;
bfs();
cout << bestw;
}
7-18 狼人杀
#include <bits/stdc++.h>using namespace std;
typedef long long ll;
const ll N = 2e5 + 10;
ll n, m;
ll l, flag;
ll a[N];
ll honest[N];//每个人是否为狼人:1为好人,-1为狼人
vector<ll> ans, ve;//分别为临时假设为狼人的人,和最终是狼人的人void dfs(ll idx, ll num) {//idx代表当前遍历的下标,num为当前狼人的数量if (num == m && flag == 0) {//如果狼人数量有m个时候,并且没有找到答案ve.push_back(idx);//假设我们idx这个人为狼人honest[idx] = -1;//假设这个狼人ll cnt = 0;//存狼人说谎的人数ll lie = 0;//存说谎的人for (ll i = 1; i <= n; i++) {if (a[i] * honest[abs(a[i])] < 0) {//如果描述的这个个人的身份和当前人假设的身份不同,说明这个人说谎了lie++;//将说谎的人存进去if (honest[i] == -1) cnt++;//如果这个人是狼人并且说谎了}}if (lie == l && cnt >= 1 && cnt < m) {//当前说谎人数满足l,并且并不是所以狼人在说谎ans = ve;//将当前狼人赋给ansflag = 1;//找到了答案,标记}honest[idx] = 1;//将狼人赋回好人ve.pop_back();//删掉这个人}if (num > m || idx < 1 || flag == 1) return;//找到过答案或者超过边界退出ve.push_back(idx);//假设idx为狼人honest[idx] = -1;//将idx标为狼人dfs(idx - 1, num + 1);//狼人数量+1honest[idx] = 1;//将idx标为好人ve.pop_back();//删掉这个人dfs(idx - 1, num);//假设这个人是好人
}int main() {cin >> n >> m >> l;for (ll i = 1; i <= n; i++) {cin >> a[i];honest[i] = 1;//假设每个人都说真话}dfs(n, 1);//因为要找到最大的那组答案,所以倒着遍历下标if (ans.size() == 0)cout << "No Solution" << endl;//如果没有将答案赋值给ans过即没有答案else {for (ll i = 0; i < ans.size(); i++) {//输出if (i != 0) cout << " ";cout << ans[i];}}
}
7-19 还原文件
#include<bits/stdc++.h>
#define llu unsigned long long
using namespace std;vector<int> ans,f[110];
int a[100010],n,m;
bool vis[110];
bool flag1,flag2;//flag1代表纸条是否已经全部拼接上,//flag2代表当前的纸条是否能够拼接上。
void dfs(int now)
{
if(ans.size()==m)
{flag1=1;for(int i=0;i<m;i++){if(i)cout << " " ;cout << ans[i] ;}
}
if(flag1)return ;
for(int i=1;i<=m;i++)
{if(vis[i])continue;flag2=0;for(int j=0;j<f[i].size();j++){if(f[i][j]!=a[now+j]){flag2=1;break;}}if(flag2)continue;ans.push_back(i);vis[i]=1;dfs(now+f[i].size()-1);vis[i]=0;ans.pop_back();
}
}int main()
{
cin >> n ;
for(int i=0;i<n;i++)
{cin >> a[i] ;
}
cin >> m ;
for(int i=1;i<=m;i++)
{int k;cin >> k ;for(int j=0;j<k;j++){int t;cin >> t ;f[i].push_back(t);}
}
dfs(0);
return 0;
}
7-20 救援计划
#include <iostream>
#include <queue>
#include <vector>
#include <tuple>using namespace std;struct Position {int x, y;int time;
};const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};int main() {int N, M;while (cin >> N >> M) {vector<vector<char>> prison(N, vector<char>(M));Position start;bool found = false;// Read the prison layout and find the starting positionfor (int i = 0; i < N; i++) {for (int j = 0; j < M; j++) {cin >> prison[i][j];if (prison[i][j] == 'a') {start = {i, j, 0};}}}queue<Position> q;vector<vector<bool>> visited(N, vector<bool>(M, false));q.push(start);visited[start.x][start.y] = true;while (!q.empty()) {Position curr = q.front();q.pop();// Check if we reached a friend or guardif (prison[curr.x][curr.y] == 'r') {cout << curr.time << endl; // Output the time including the time to kill guardsfound = true;break;}// Try all four directionsfor (int i = 0; i < 4; i++) {int newX = curr.x + dx[i];int newY = curr.y + dy[i];int newTime = curr.time + 1;if (newX >= 0 && newX < N && newY >= 0 && newY < M && !visited[newX][newY] && prison[newX][newY] != '#') {visited[newX][newY] = true;// If there's a guard, increment time and continueif (prison[newX][newY] == 'x') {newTime++;}q.push({newX, newY, newTime});}}}if (!found) {cout << "No way!" << endl;}}return 0;
}
7-21 魔法楼梯
#include <iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int dr[4][2]={{1,0},{-1,0},{0,1},{0,-1} };// 楼梯方向设置对后面判断有影响
struct node
{int x,y,ti;
};char mp[25][25];
int ti[25][25];
int n,m,i,j,sx,sy,tx,ty;int bfs()
{node p;queue<node> s;p.x=sx;p.y=sy;p.ti=0;ti[sx][sy]=0;s.push(p);while(!s.empty()){node q=s.front();s.pop();for(int i=0;i<4;i++){int xx=q.x+dr[i][0];int yy=q.y+dr[i][1];if (xx>=0 && xx<n && yy>=0 && yy<m && mp[xx][yy]!='*'){p.ti=q.ti+1;if(mp[xx][yy]=='|' || mp[xx][yy]=='-') //关键{int xxx=xx+dr[i][0];int yyy=yy+dr[i][1];if(mp[xxx][yyy]=='*' || xxx<0 ||xxx>=n || yyy<0 || yyy>=m ) continue;if(mp[xx][yy]=='|'){if(q.ti%2==1 && i<=1 || q.ti%2==0 && i>1) p.ti++;} elseif (mp[xx][yy]=='-')if(q.ti%2==1 && i>1 || q.ti%2==0 && i<=1) p.ti++;xx=xxx;yy=yyy;}if(p.ti<ti[xx][yy]){p.x=xx;p.y=yy;ti[xx][yy]=p.ti;s.push(p);}if(xx==tx && yy==ty) return ti[xx][yy];}}}
}
int main()
{while(~scanf("%d%d",&n,&m)){for(i=0;i<n;i++){scanf("%s",mp[i]);for(j=0;j<m;j++){if (mp[i][j]=='S') {sx=i,sy=j;mp[i][j]='.';}if (mp[i][j]=='T') {tx=i,ty=j;mp[i][j]='.';}}}memset(ti,10000,sizeof(ti));printf("%d\n",bfs());}return 0;
}