手热做了四道,还行
大概就是在一个自行车管理监控系统中,你会实时得到各个站点含有的自行车数,我们需要从PBMC出发到达给出的存在问题的站点使其变成完美状态(也需要使途径的站点变成完美状态,完美状态是指站点的自行车数等于Cmax/2)
去年做的时候学别人直接dfs,做得晕头转向。这回直接拆成dijkstra+dfs思路清晰了很多
利用dijkstra配合前驱结点序列得到最短路径,再利用dfs得到最小返回minback和最小带走mintake
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
//c:capacity,n:,sp:index of problem station, m: number of roads
ll c, n, sp, m, r1, r2, ph;
const int inf = 99999999;
ll bk[510]; //current bike
ll dist[510]; //
vector<ll> pre[510], tempath, path;
ll road[510][510];
ll mintake = inf, minback = inf;//dfs
bool visited[510];
//output: bike sent from PBMC
//if the path is not unique(take equal time), output the one that sent minimum bike to PBMC
void dfs(ll curcity)
{
tempath.push_back(curcity);
if (curcity == 0) //PBMC,清算take和back
{
ll take = 0, back = 0;
for (ll i = tempath.size() - 1; i >= 0; --i)
{
ll id = tempath[i];
if (bk[id] > 0) {back += bk[id];} //back
else
{
if (back > (0 - bk[id]))
{
back += bk[id];
}
else
{
take += ((0 - bk[id]) - back);
back = 0;
}
}
}
if (take < mintake)
{
mintake = take;
minback = back;
path = tempath;
}
else if (take == mintake and back < minback)
{
minback = back;
path = tempath;
}
tempath.pop_back();
return;
}
for (ll i = 0; i < pre[curcity].size(); ++i)
{
dfs(pre[curcity][i]);
}
tempath.pop_back();
}
int main(void)
{
cin>>c>>n>>sp>>m;
for (ll i = 0; i < 510; ++i) {dist[i] = inf;}
for (ll i = 0; i < 510; ++i)
{
for (ll j = 0; j < 510; ++j) {road[i][j] = inf;}
}
memset(visited, false, sizeof(visited));
for(ll i = 1; i <= n; ++i)
{
cin>>bk[i];
bk[i] = bk[i] - c / 2; //预处理
}
for (ll i = 0; i < m; ++i)
{
cin>>r1>>r2>>ph;
road[r1][r2] = road[r2][r1] = ph;
}
for (ll i = 0; i < 510; ++i) {road[i][i] = 0;}
dist[0] = 0;
//dijkstra求最短路径
for (ll i = 0; i <= n; ++i)
{
ll index = -1, tmpdist = inf;
for(ll j = 0; j <= n; ++j)
{
if (!visited[j] and dist[j] < tmpdist)
{
tmpdist = dist[j];
index = j;
}
}
if (index == -1) {break;}
visited[index] = 1;
for (ll j = 0; j <= n; ++j)
{
if (!visited[j] and road[j][index] != inf)
{
if (road[j][index] + dist[index] < dist[j])
{
dist[j] = road[j][index] + dist[index];
pre[j].clear();
pre[j].push_back(index);
}
else if (road[j][index] + dist[index] == dist[j])
{
pre[j].push_back(index);
}
}
}
}
//dfs确定最小send和最小take
dfs(sp);
cout<<mintake<<" ";
ll index = 0;
for (ll i = path.size() - 1; i >= 0; --i)
{
if (index == 0)
{
cout<<path[i];
index++;
}
else {cout<<"->"<<path[i];}
}
cout<<" "<<minback;
return 0;
}
1019.General Palindromic Number
有手就行,直接上代码
#include <bits/stdc++.h>
using ll = long long;
using namespace std;
ll digit, n;
int main(void)
{
cin>>n>>digit;
//if (n > 0 % n < 10) {cout<<"Yes"<<endl; cout<<n<<endl; return 0;}
vector<ll> ans;
while (n)
{
ans.push_back(n % digit);
n /= digit;
}
ll i = 0, j = ans.size() - 1;
bool f = true;
while (i < j)
{
if (ans[i] != ans[j]) {f = false; break;}
i += 1;
j -= 1;
}
if (f) {cout<<"Yes"<<endl;}
else {cout<<"No"<<endl;}
for (ll index = ans.size() - 1; index >= 0; --index)
{
if (index == 0) {cout<<ans[index];}
else {cout<<ans[index]<<" ";}
}
return 0;
}
1020.Tree Traverals感觉一般般吧,通过后序遍历和中序遍历递归得到树结构,之前leetcode树的题做了不少,直接搬了leetcode给的树板子,层序遍历(广度优先)也算是老生常谈
直接代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll post[50];
ll in[50];
ll n;
class TreeNode
{
public:
ll val;
TreeNode* left;
TreeNode* right;
TreeNode():left(nullptr), right(nullptr){}
TreeNode(ll val):val(val), left(nullptr), right(nullptr){}
};
TreeNode* traversal(ll root, ll left, ll right)
{
if (left > right) {return nullptr;}
ll idx = left;
while (post[root] != in[idx]) {idx++;}
TreeNode* t = new TreeNode(post[root]);
t->left = traversal(root - (right - idx) - 1, left, idx - 1);
t->right = traversal(root - 1, idx + 1, right);
return t;
}
int main(void)
{
ll n;
cin>>n;
for (ll i = 0; i < n; ++i) {cin>>post[i];}
for (ll i = 0; i < n; ++i) {cin>>in[i];}
TreeNode* root = traversal(n - 1, 0, n - 1);
queue<TreeNode*> q;
q.push(root);
ll idx = 0;
while (!q.empty())
{
ll len = q.size();
for (ll i = 0; i < len; ++i)
{
TreeNode* tmp = q.front();
q.pop();
if (idx == 0) {cout<<tmp->val; idx++;}
else {cout<<" "<<tmp->val;}
if (tmp->left) {q.push(tmp->left);}
if (tmp->right) {q.push(tmp->right);}
}
}
return 0;
}
1021.Deepest Root
这个的确不是太难,主要是连通分量判断吧,只要输入点同时已经被访问过,那么连通分量就会加一
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
vector<vector<ll>> road(10001);
bool visited[10001];
ll n, r1, r2;
ll maxpath, finpath;
void dfs(ll root, ll curlen)
{
if (visited[root]) {return;}
visited[root] = true;
curlen += 1;
if (curlen > maxpath) {maxpath = curlen;}
for (ll i = 0; i < road[root].size(); ++i)
{
dfs(road[root][i], curlen);
}
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for (ll i = 1; i <= n; ++i) {visited[i] = false;}
ll connected = 1;
for (ll i = 0; i < n - 1; ++i)
{
cin>>r1>>r2;
road[r1].push_back(r2);
road[r2].push_back(r1);
if (visited[r1] and visited[r2]) {connected += 1;}
else {visited[r1] = visited[r2] = true;}
//需要在这里判断连通分量的个数
}
if (connected > 1) {cout<<"Error: "<<connected<<" components"<<endl; return 0;}
vector<ll> ans;
for (ll i = 1; i <= n; ++i)
{
for (ll j = 1; j <= n; ++j) {visited[j] = false;}
maxpath = 0;
dfs(i, 0);
if (maxpath > finpath)
{
ans.clear();
ans.push_back(i);
finpath = maxpath;
}
else if (maxpath == finpath) {ans.push_back(i);}
}
for (ll i = 0; i < ans.size(); ++i)
{
cout<<ans[i]<<endl;
}
return 0;
}
后面三个题没什么营养,也会de几次,并不是一遍过。
睡了睡了。