7-1 最大公约数 (15 分)
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,x,y,z;
while(cin >> n)
{
while(n --){
cin >> x >> z;
int t = x / z;
for(int i = 2;;i ++){
if(__gcd(i,t) == 1)
{
cout << i * z << endl;
break;
}
}
}
}
return 0;
}
7-2 查找整数 (10 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10 ;
int a[N];
int main()
{
int n,x;
cin >> n >> x;
for(int i = 1,p;i <= n;i ++){
cin >> p;
a[p] = i;
}
if(a[x]) cout << a[x] - 1 << endl;
else cout << "Not Found" << endl;
return 0;
}
7-3 矩阵A乘以B (15 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[N][N];
int b[N][N];
int c[N][N];
int main()
{
int ra,ca,rb,cb;
cin >> ra >> ca;
for(int i = 1;i <= ra;i ++)
for(int j = 1;j <= ca;j ++)
cin >> a[i][j];
cin >> rb >> cb;
for(int i = 1;i <= rb;i ++)
for(int j = 1;j <= cb;j ++)
cin >> b[i][j];
if(ca != rb){
printf("Error: %d != %d\n",ca,rb);
}else{
for(int i = 1;i <= ra;i ++){
for(int k = 1;k <= cb;k ++){
int sum = 0;
for(int j = 1;j <= ca;j ++){
sum += a[i][j] * b[j][k];
}
c[i][k] = sum;
}
}
cout << ra << ' ' << cb << endl;
for(int i = 1;i <= ra;i ++)
{
for(int j = 1;j <= cb;j ++){
if(j == cb){
cout << c[i][j];
continue;
}
cout << c[i][j] << ' ';
}
cout << endl;
}
}
return 0;
}
7-4 IP地址转换 (20 分)
#include <bits/stdc++.h>
using namespace std;
int main()
{
string str;
cin >> str;
string ans;
vector<int>vec;
for(int i = 0;i < str.size();i ++){
ans = ans + str[i];
if(ans.size() == 8){
reverse(ans.begin(),ans.end());
int sum = 0;
for(int i = 0;i < 8;i ++){
sum += (1 << i) * (ans[i] - '0');
}
vec.push_back(sum);
ans.clear();
}
}
for(int i = 0;i < 4;i ++){
if(i == 3){
cout << vec[i];
}else
cout << vec[i] << '.';
}
return 0;
}
7-5 汉诺(Hanoi)塔问题 (20 分)
#include <bits/stdc++.h>
using namespace std;
void hanoi(int n,char a,char b,char c)
{
if(n == 1){
cout << a << "-->" << c << endl;
}else{
hanoi(n - 1,a,c,b);
cout << a << "-->" << c << endl;
hanoi(n - 1,b,a,c);
}
}
int main()
{
int n;
cin >> n;
char a = 'a',b = 'c',c = 'b';
hanoi(n,a,b,c);
return 0;
}
7-6 选择法排序 (20 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 11;
int a[N];
int main()
{
int n;
cin >> n;
for(int i = 0;i < n;i ++)
cin >> a[i];
sort(a ,a + n);
reverse(a ,a + n);
for(int i = 0;i < n;i ++){
cout << a[i];
if(i != n - 1) cout << ' ';
}
return 0;
}
7-7 选择法排序之过程 (15 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int main()
{
int n;
cin >> n;
for(int i = 0;i < n;i ++)
cin >> a[i];
if(n == 1){
cout << a[0] << endl;
return 0;
}
for(int i = 0;i < n - 1;i ++){
int maxn = i;
for(int j = i;j < n;j ++){
if(a[j] < a[maxn]){
maxn = j;
}
}
swap(a[i],a[maxn]);
for(int i = 0;i < n;i ++){
cout << a[i];
if(i != n - 1){
cout << ' ';
}
}
cout << endl;
}
return 0;
}
7-8 冒泡法排序 (20 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int main()
{
int n,k;
cin >> n >> k;
for(int i = 0;i < n;i ++)
cin >> a[i];
if(n == 1){
cout << a[0] << endl;
return 0;
}
while(k --){
for(int i = 0; i < n - 1;i ++){
if(a[i] > a[i + 1]){
swap(a[i],a[i + 1]);
}
}
}
for(int i = 0;i < n;i ++){
cout << a[i];
if(i != n - 1){
cout << ' ';
}
}
return 0;
}
7-9 字符串的冒泡排序 (20 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
string a[N];
int main()
{
int n,k;
cin >> n >> k;
for(int i = 0;i < n;i ++)
cin >> a[i];
if(n == 1){
cout << a[0] << endl;
return 0;
}
while(k --){
for(int i = 0; i < n - 1;i ++){
if(a[i] > a[i + 1]){
swap(a[i],a[i + 1]);
}
}
}
for(int i = 0;i < n;i ++){
cout << a[i] << endl;
}
return 0;
}
7-10 冒泡法排序之过程 (15 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int main()
{
int n,k;
cin >> n;
for(int i = 0;i < n;i ++)
cin >> a[i];
if(n == 1){
cout << a[0] << endl;
return 0;
}
for(int j = 0;j < n - 1;j ++){
for(int i = 0; i < n - 1;i ++){
if(a[i] > a[i + 1]){
swap(a[i],a[i + 1]);
}
}
for(int i = 0;i < n;i ++){
cout << a[i];
if(i != n - 1){
cout << ' ';
}
}
cout << endl;
}
return 0;
}
7-11 串的模式匹配 (30 分)
- 字符串hash,kmp也可以做
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef unsigned long long ULL;
ULL P = 131;
char str[N];
ULL h[N], p[N]; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64
// 初始化
// 计算子串 str[l ~ r] 的哈希值
ULL get(int l, int r)
{
return h[r] - h[l - 1] * p[r - l + 1];
}
char str1[N];
ULL h1[N], p1[N]; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64
// 初始化
// 计算子串 str[l ~ r] 的哈希值
ULL get1(int l, int r)
{
return h1[r] - h1[l - 1] * p1[r - l + 1];
}
int main()
{
cin >> str + 1;
cin >> str1 + 1;
int n = strlen(str + 1);
int m = strlen(str1 + 1);
if(n < m) {
cout << 0 << endl;
return 0;
}
p[0] = 1;
for (int i = 1; i <= n; i ++ )
{
h[i] = h[i - 1] * P + str[i];
p[i] = p[i - 1] * P;
}
p1[0] = 1;
for (int i = 1; i <= m; i ++ )
{
h1[i] = h1[i - 1] * P + str1[i];
p1[i] = p1[i - 1] * P;
}
ULL l2 = get1(1,m);
//cout << l2 << ' ' << m << endl;
for(int i = 1;i <= n - m + 1;i ++){
// cout << get(i,i + m - 1) << endl;
if(get(i,i + m - 1) == l2){
cout << i << endl;
return 0;
}
}
cout << 0 << endl;
return 0;
}
7-12 字符串模式匹配 (5 分)
- 在上面输出ne数组,在下面是不对的
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
char s[N],p[N];
int ne[N];
int main()
{
scanf("%s",s+1);
scanf("%s",p+1);
int n = strlen(s+1);
int m = strlen(p+1);
int f = -1;
printf("%d ",ne[1]-1);
for (int i = 2 , j = 0 ; i <= m ; i ++ )
{
while(j && p[i] != p[j+1]) j = ne[j];
if(p[i] == p[j+1]) j ++ ;
ne[i] = j;
printf("%d ",ne[i]-1);
}
for (int i = 1 , j = 0 ; i <= n ; i ++ )
{
while(j && s[i] != p[j+1]) j = ne[j];
if(s[i] == p[j+1]) j ++ ;
if(j == m)
{
f = i - m;
break;
}
}
printf("\n");
printf("%d\n",f);
return 0;
}
7-13 图深度优先遍历 (10 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef unsigned long long ULL;
vector<int>v[N];
vector<int>ans;
bool st[N];
void dfs(int p){
ans.push_back(p);
for(auto &x : v[p]){
if(st[x]) continue;
st[x] = true;
dfs(x);
}
}
int main()
{
int n,m;
cin >> n >> m;
for(int i = 0;i < m;i ++){
int a,b;
cin >> a >> b;
v[a].push_back(b);
}
for(int i = 0;i < n;i ++){
sort(v[i].begin(),v[i].end());
}
for(int i = 0;i < n;i ++){
if(st[i]) continue;
st[i] = true;
dfs(i);
}
// dfs(0);
for(auto &x : ans){
cout << x << ' ';
}
return 0;
}
7-14 图的先深搜索 (15 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef unsigned long long ULL;
int h[N],e[N],ne[N],idx;
void add(int a,int b){
e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
}
bool st[N];
vector<int>ans;
void dfs(int p,int fa)
{
ans.push_back(p);
for(int i = h[p];~i;i = ne[i]){
int j = e[i];
if(st[j] || j == fa) continue;
st[j] = true;
dfs(j,p);
}
}
int main()
{
memset(h,-1,sizeof h);
int n,m,s;
cin >> n >> m >> s;
for(int i = 0;i < m;i ++){
int a,b;
cin >> a >> b;
add(a,b);
add(b,a);
}
st[s] = true;
dfs(s,0);
for(auto &x: ans){
cout << x << ' ';
}
cout << endl;
if(ans.size() != n) cout << 0 << endl;
return 0;
}
7-15 迷宫-广度策略 (80 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1100;
typedef pair<int,int> PII;
int g[N][N];
int dx[] = {0,1,1,1,0,-1,-1,-1};
int dy[] = {1,1,0,-1,-1,-1,0,1};
int fx,fy,sx,sy;
int n;
PII pre[N][N];
bool st[N][N];
void bfs()
{
queue<PII> q;
q.push({sx,sy});
pre[sx][sy] = {-1,-1};
while(q.size()){
auto t = q.front();
q.pop();
int x = t.first,y = t.second;
for(int i = 0;i < 8;i ++){
int a = x + dx[i],b = y + dy[i];
if(a < 0 || a >= n || b < 0 || b >= n) continue;
if(g[a][b] || st[a][b]) continue;
st[a][b] = true;
pre[a][b] = t;
if(t.first == fx && t.second == fy) return;
q.push({a,b});
}
}
}
void dfs(int x,int y)
{
cout << x << ' ' << y << ';';
if(x == sx && y == sy) return;
dfs(pre[x][y].first,pre[x][y].second);
}
int main()
{
cin >> n;
for(int i = 0;i < n;i ++)
for(int j = 0;j < n;j ++)
cin >> g[i][j];
cin >> sx >> sy >> fx >> fy;
bfs();
dfs(fx,fy);
return 0;
}
7-16 图的先广搜索 (15 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
typedef unsigned long long ULL;
int h[N],e[N],ne[N],idx;
void add(int a,int b){
e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
}
bool st[N];
vector<int>ans;
void bfs(int p)
{
queue<int>q;
q.push(p);
while(q.size())
{
auto t = q.front();
q.pop();
ans.push_back(t);
for(int i = h[t];~i;i = ne[i]){
int j = e[i];
if(st[j]) continue;
st[j] = true;
q.push(j);
}
}
}
int main()
{
memset(h,-1,sizeof h);
int n,m,s;
cin >> n >> m >> s;
for(int i = 0;i < m;i ++){
int a,b;
cin >> a >> b;
add(a,b);
add(b,a);
}
st[s] = true;
bfs(s);
for(auto &x: ans){
cout << x << ' ';
}
cout << endl;
if(ans.size() != n) cout << 0 << endl;
return 0;
}
7-17 插入排序还是归并排序 (25 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1100;
int n;
int a[N];
int c[N];
int b[N];
bool check(int a[],int b[]){
for(int i = 1;i <= n;i ++){
if(a[i] != b[i]) return false;
}
return true;
}
void insertsort()
{
bool flag = false;
for(int i = 2;i <= n;i ++){
sort(a + 1,a + 1 + i);
if(flag){
cout << "Insertion Sort" << endl;
for(int i = 1;i <= n;i ++){
if(i == n) cout << a[i];
else
cout << a[i] << ' ';
}
return;
}
if(check(a,b)){
flag = true;
}
}
}
void mergesort()
{
bool flag = false;
for(int i = 2;;i *= 2){
for(int j = 0;j < n;j += i){
int r = j + i;
if(r > n) r = n;
sort(c + 1 + j,c + 1 + r);
}
if(flag){
cout << "Merge Sort" << endl;
for(int i = 1;i <= n;i ++){
if(i == n) cout << c[i];
else
cout << c[i] << ' ';
}
return;
}
if(check(c,b)){
flag = true;
}
if(i > n) return;
}
}
int main()
{
cin >> n;
for(int i = 1;i <= n;i ++)
{
cin >> a[i];
c[i] = a[i];
}
for(int i = 1;i <= n;i ++)
cin >> b[i];
insertsort();
mergesort();
return 0;
}
7-18 插入排序还是堆排序 (25 分)
- 百度
#include <iostream>
using namespace std;
const int N = 110;
int n;
int a[N], b[N];
void down(int u, int size)
{
int t = u;
if (u * 2 <= size && b[t]<b[u * 2]) t = u * 2;
if (u * 2 + 1 <= size && b[t]<b[u * 2 + 1]) t = u * 2 + 1;
if (t != u)
{
swap(b[t], b[u]);
down(t, size);
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
int p = 2;
while (p <= n && b[p] >= b[p - 1]) p++;
int k = p;
while (p <= n && a[p] == b[p]) p++;
if (p == n + 1)//说明是插入排序
{
cout << "Insertion Sort" << endl;
while (k>1 && b[k]<b[k - 1]) swap(b[k], b[k - 1]), k--;
}
else //否则说明一定是堆排序
{
cout << "Heap Sort" << endl;
p = n;
while (b[1] <= b[p]) p--;
swap(b[1], b[p]);
down(1, p - 1);
}
cout << b[1];
for (int i = 2; i <= n; i++) cout << ' ' << b[i];
cout << endl;
return 0;
}
7-19 判断一个有向图是否能够完成拓扑排序 (90 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int h[N],e[N],ne[N],idx;
void add(int a,int b){
e[idx] = b,ne[idx] = h[a],h[a] = idx ++;
}
bool st[N];
int din[N];
int n;
bool topsort()
{
queue<int>q;
for(int i = 0;i <= n;i ++){
if(!din[i]) q.push(i);
}
int cnt = 0;
while(q.size()){
auto t = q.front();
cnt ++;
q.pop();
for(int i = h[t];~i;i = ne[i]){
int j = e[i];
din[j] --;
if(din[j] == 0){
q.push(j);
}
}
}
return cnt == n + 1;
}
int main()
{
memset(h,-1,sizeof h);
int a,b;
while(cin >> a >> b){
if(a == -1 && b == -1) break;
add(a,b);
din[b] ++;
n = max({a,b,n});
}
cout << topsort() << endl;
return 0;
}
7-20 全排列 (30 分)
- 康托展开,逆康托展开
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
LL fact(LL x)
{
LL res = 1;
for (LL i = 2; i <= x; ++ i) res *= i;
return res;
}
string uncantor(int n, LL inx) // 求在长度为n的序列中,从小到达排列,排第inx的序列是多少(从1开始)
{
string res;
int vis[n * n];
memset(vis, 0, sizeof vis);
-- inx; // 比当前序列小的序列有inx个
for (int i = (n - 1); ~i; -- i)
{
LL c = inx / fact(i), s = inx % fact(i);
LL cnt = 0, num;
for (LL j = 1; j <= n; ++ j)
{
if (!vis[j]) ++ cnt;
if (cnt == c + 1) // 找到第c+1小的数
{
num = j;
break;
}
}
vis[num] = 1;
res += to_string(num);
res += ' ';
inx = s;
}
res.pop_back();
return res;
}
int main()
{
LL t;
cin >> t;
while(t --){
LL n,m;
cin >> n >> m;
cout << uncantor(n, m) << endl;
}
return 0;
}
- 7-21
// 我自己写的代码,不优美但是应该没啥问题
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
string str;
for(int i = 1;i <= n;i ++){
str += i + '0';
}
do
{
cout << str << endl;
} while (next_permutation(str.begin(), str.end()));
}
- 7-22
// 我自己写的代码,不优美但是应该没啥问题
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
set<int>s1,s2;
cin >> n >> m;
for(int i = 0;i < n;i ++){
int x;
cin >> x;
s1.insert(x);
}
for(int i = 0;i < m;i ++){
int x;
cin >> x;
if(s1.count(x)){
s2.insert(x);
}
}
cout << s2.size() << endl;
bool flag = false;
for(auto &x : s2){
if(flag) cout << ' ';
flag = true;
cout << x;
}
return 0;
}
- 7-23
#include <iostream>
using namespace std;
#include <vector>
struct Node{
int data;
Node*next;
};
int main()
{
int n, m;
cin >> n >> m;
vector<int>res;
Node * first = new Node;
//first->next =nullptr;
Node *pre = new Node;
Node * p = new Node;
pre = first;
pre->next = p;
p = first;
if (n){
pre->data = 1;
}
for (int i = 2; i <= n; i++)
{
Node * pc = new Node;
pc->data = i;
pc->next = nullptr;
p->next = pc;
p = pc;
}
p->next = pre;
//cout << "pre->data = " << pre->data <<"p->next = "<<p->data<< endl;
int cnt = 1;
for (auto i = pre,j = p;n; i = i->next)
{
if (cnt == m)
{
auto pr = i;
res.push_back(i->data);
//cout << i->data << " ";
j->next = i->next;
//delete pr;
n--;
cnt = 0;
}
cnt++;
j = i;
//system("pause");
}
bool tf = false;
for (auto &x : res)
{
if (tf)
cout << " ";
cout << x;
tf = true;
}
system("pause");
return 0;
}
- 7-24 二分查找 (20 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1100;
int a[N];
int main()
{
int n;
cin >> n;
for(int i =0;i < n;i ++){
cin >> a[i];
}
int x;
cin >> x;
int l = 0,r = n - 1;
int cnt = 0;
while(l < r){
int mid = l + r + 1 >> 1;
cnt ++;
if(a[mid] > x){
r = mid - 1;
}else{
l = mid;
}
}
if(a[l] != x) l = -1;
cout << l << endl;
cout << cnt << endl;
return 0;
}
- 7-25 两个有序序列的中位数 (25 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N];
int b[N];
int c[N];
int main()
{
int n;
cin >> n;
for(int i = 0;i < n;i ++){
cin >> a[i];
}
for(int i = 0;i < n;i ++){
cin >> b[i];
}
int cnt = 0;
int i,j;
for(i = 0,j = 0;i < n && j < n;)
{
if(a[i] > b[j]){
c[cnt ++] = b[j];
j ++;
}else{
c[cnt ++] = a[i];
i ++;
}
}
for(int k = i;k < n;k ++){
c[cnt ++] = a[k];
}
for(int k = j;k < n;k ++){
c[cnt ++] = b[k];
}
/* for(int i = 0;i < cnt;i ++){
cout << c[i] << ' ';
}*/
cout << c[(n * 2 - 1) >> 1] << endl;
return 0;
}
- 7-26
#include <bits/stdc++.h>
using namespace std;
const int N = 11;
pair<char,char>tree[N];
int din[N];
vector<int> vec;
void bfs(int p)
{
queue<int>q;q.push(p);
while(q.size())
{
p = q.front();q.pop();
if(tree[p].first == '-' && tree[p].second == '-'){
vec.push_back(p);
}
if(tree[p].first != '-'){
int t = tree[p].first - '0';
q.push(t);
}
if(tree[p].second != '-'){
int t = tree[p].second - '0';
q.push(t);
}
}
}
int main()
{
int n;
cin >> n;
for(int i = 0;i < n;i ++)
{
char l,r;
cin >> l >> r;
tree[i].first = l;
tree[i].second = r;
if(l != '-'){
int t = l - '0';
din[t] ++;
}
if(r != '-'){
int t = r - '0';
din[t] ++;
}
}
int root = 0;
for(int i = 0;i < n;i ++){
if(din[i] == 0) root = i;
}
bfs(root);
for(int i = 0;i < vec.size();i ++){
if(i == vec.size() - 1){
cout << vec[i] << endl;
}else{
cout << vec[i] << ' ';
}
}
return 0;
}
- 7-27
#include<stdio.h>
#include<stdlib.h>
struct tree
{
struct tree* leftchild;
int data;
struct tree* rightbrother;
};
int answer;
struct tree* front;
struct tree* rear;
int path[100];
void create(struct tree* p) //创建树
{
struct tree* left,*right;
int a;
scanf("%d",&a);
if(a==0)
{
p->data=0;
return;
}
else
{
left=(struct tree*)malloc(sizeof(struct tree));
right=(struct tree*)malloc(sizeof(struct tree));
p->data=a;
p->leftchild=left;
p->rightbrother=right;
create(p->leftchild);
create(p->rightbrother);
}
};
int maxnum(int a,int b,int c) //比较最大值
{
if(a>=b&&a>=c)
return a;
if(b>a&&b>c)
return b;
if(c>b&&c>a)
return c;
}
int minnum(int a,int b,int c) //比较最小值
{
if(a<=b&&a<=c)
return a;
if(b<a&&b<c)
return b;
if(c<b&&c<a)
return c;
}
void dpxian(struct tree* p,int max,int min) //在先根遍历中更新状态
{
int a=max;
int b=min;
max=maxnum(p->data*a,p->data*b,p->data); //状态转移,由于负数的存在,需要一个最大一个最小
min=minnum(p->data*a,p->data*b,p->data);
if(answer<max)
{
if(max==p->data)
front=p;
answer=max;
rear=p;
}
if(p->leftchild->data!=0)
dpxian(p->leftchild,max,min);
while(p->rightbrother->data!=0)
{
dpxian(p->rightbrother,a,b);//使用上一层的最大和最小值
p=p->rightbrother;
}
}
void print(struct tree* p,int path[],int dep)
{
if(p->data==0)
return;
path[dep]=p->data;
if(p==rear)
{
int i;
for(i=0;i<=dep;i++)
printf("%d ",path[i]);
exit;
}
print(p->leftchild,path,dep+1);
print(p->rightbrother,path,dep);
}
int main(void)
{
struct tree* head;
int dep=0;
int path[100];
int i,a[100]={0}; //树的深度初始化时要从0开始
head=(struct tree*)malloc(sizeof(struct tree));
create(head);
int max=1,min=1;//动态规划状态
dpxian(head,max,min);
printf("%d\n",answer);
print(front,path,dep);
return 0;
}
- 7-28
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int a[N];
int main()
{
ios::sync_with_stdio(false);
int n,k;
cin >> n >> k;
for(int i = 0;i < n;i ++)
cin >> a[i];
sort(a,a+n);
cout << a[n-k] << endl;
return 0;
}
- 7-29
3 3 4 4 8 8 9 9
3 2 0 4 8 7 7 9
5 2 2 6 10 10 7 11
5 5 6 6 1 10 11 11
13 13 14 1 1 18 19 19
13 12 14 14 18 18 17 19
15 12 12 16 20 17 17 21
15 15 16 16 20 20 21 21
- 7-30
1 2 3 4 5 6 7 8
2 1 4 3 6 5 8 7
3 4 1 2 7 8 5 6
4 3 2 1 8 7 6 5
5 6 7 8 1 2 3 4
6 5 8 7 2 1 4 3
7 8 5 6 3 4 1 2
8 7 6 5 4 3 2 1
- 7-31
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int n,k;
int BinarySearch1(int x)
{
int l = 0,r = n - 1;
while(l < r){
int mid = l + r >> 1;
if(a[mid] < x){
l = mid + 1;
}else{
r = mid;
}
}
return l;
}
int BinarySearch2(int x)
{
int l = 0,r = n - 1;
while(l < r){
int mid = l + r + 1 >> 1;
if(a[mid] > x){
r = mid - 1;
}else{
l = mid;
}
}
return l;
}
int main()
{
cin >> n >> k;
for(int i = 0;i < n;i ++) cin >> a[i];
if(k < a[0]){
cout << "-1 0" << endl;
}else if(k > a[n - 1]){
cout << n - 1 << ' ' << n << endl;
}else{
int l1 = BinarySearch1(k);
int l2 = BinarySearch2(k);
cout << l2 << ' ' << l1 << endl;
}
return 0;
}
- 7-32
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int n,k;
typedef long long LL;
int main()
{
cin >> n;
for(int i = 0,x;i < n;i ++)
cin >> x >> a[i];
sort(a,a+n);
int mid = a[n >> 1];
LL sum = 0;
for(int i = 0;i < n;i ++){
sum += fabs(a[i] - mid);
}
cout << sum << endl;
return 0;
}
/*
1,3,8
4-1+4-3+8-4
*/
- 7-33
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int a[N];
int n,k;
int BinarySearch1(int x)
{
int l = 0,r = n - 1;
while(l < r){
int mid = l + r >> 1;
if(a[mid] < x){
l = mid + 1;
}else{
r = mid;
}
}
return l;
}
int BinarySearch2(int x)
{
int l = 0,r = n - 1;
while(l < r){
int mid = l + r + 1 >> 1;
if(a[mid] > x){
r = mid - 1;
}else{
l = mid;
}
}
return l;
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> k;
for(int i = 0;i < n;i ++) cin >> a[i];
if(k < a[0]){
cout << a[0] << endl;
}else if(k > a[n - 1]){
cout << a[n - 1] << endl;
}else{
int l1 = BinarySearch1(k);
int l2 = BinarySearch2(k);
int f1 = k - a[l2],f2 = a[l1] - k;
if(f1 <= f2){
cout << a[l2] << endl;
}else{
cout << a[l1] << endl;
}
}
return 0;
}
- 7-34
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 30;
int l[N], r[N], v[N], h[N], idx;
void update(int u)
{
h[u] = max(h[l[u]], h[r[u]]) + 1;
}
void R(int& u)
{
int p = l[u];
l[u] = r[p], r[p] = u;
update(u), update(p);
u = p;
}
void L(int& u)
{
int p = r[u];
r[u] = l[p], l[p] = u;
update(u), update(p);
u = p;
}
int get_balance(int u)
{
return h[l[u]] - h[r[u]];
}
void insert(int& u, int w)
{
if (!u) u = ++ idx, v[u] = w;
else if (w < v[u])
{
insert(l[u], w);
if (get_balance(u) == 2)
{
if (get_balance(l[u]) == 1) R(u);
else L(l[u]), R(u);
}
}
else
{
insert(r[u], w);
if (get_balance(u) == -2)
{
if (get_balance(r[u]) == -1) L(u);
else R(r[u]), L(u);
}
}
update(u);
}
int main()
{
int n, root = 0;
cin >> n;
while (n -- )
{
int w;
cin >> w;
insert(root, w);
}
cout << v[root] << endl;
return 0;
}
- 7-35
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
void PrintHeap(vector<int>& Minimum_heap);
int main()
{
int n, k, m;
scanf("%d%d", &n, &k);//n是堆的容量,需创建一个容量为n的堆。
//接下来k行,是对这个堆的依次的k项插入或删除操作:用 1 x 表示插入元素x;
//用 -1 表示删除堆顶。
vector<int> minHeap_1, minHeap_2;
make_heap(minHeap_1.begin(), minHeap_1.end(), greater<int>());
int operate_number, insert_number, i;
for(i = 0; i < k; i++)
{
scanf("%d", &operate_number);
if(operate_number == 1)
{
scanf("%d", &insert_number);
if((int)minHeap_1.size() < n)//堆满则不能插入元素
{
minHeap_1.push_back(insert_number);
push_heap(minHeap_1.begin(), minHeap_1.end(), greater<int>());
}
PrintHeap(minHeap_1);
}
else if(operate_number == -1)
{
if(!minHeap_1.empty())//堆空不可删除
{
pop_heap(minHeap_1.begin(), minHeap_1.end(), greater<int>());
minHeap_1.pop_back();
}
PrintHeap(minHeap_1);
}
}
scanf("%d", &m);
for(int i = 0; i < m; i++)
{
scanf("%d", &insert_number);
minHeap_2.push_back(insert_number);
}
make_heap(minHeap_2.begin(), minHeap_2.end(), greater<int>());
//这一步尤其关键,执行了这一句后会对vector中所有的元素做调整,使之
//成为一个最小堆
PrintHeap(minHeap_2);
return 0;
}
void PrintHeap(vector<int>& Minimum_heap)
{
int heap_size = Minimum_heap.size();
vector<int>::iterator ptr = Minimum_heap.begin();
for (int i = 1; i < heap_size; i++, ptr++)
{
printf("%d ", *ptr);
}
printf("%d\n", *ptr);
}
- 7-36
#include <bits/stdc++.h>
using namespace std;
const int N = 30;
int l[N],r[N],e[N],idx;
int h[N];
int n;
void update(int u)
{
h[u] = max(h[l[u]],h[r[u]]) + 1;
}
int get_balance(int u)
{
return h[l[u]] - h[r[u]];
}
void R(int &u)
{
int p = l[u];
l[u] = r[p];
r[p] = u;
update(u),update(p);
u = p;
}
void L(int &u)
{
int p = r[u];
r[u] = l[p];
l[p] = u;
update(u),update(p);//更新高度。
u = p;
}
void insert(int &u,int val)
{
if(u == -1) e[idx] = val,u = idx ++;
else if(val < e[u]){
insert(l[u],val);
if(get_balance(u) == 2){
if(get_balance(l[u]) == 1) R(u);
else L(l[u]),R(u);
}
}else{
insert(r[u],val);
if(get_balance(u) == -2){
if(get_balance(r[u]) != -1) R(r[u]);
L(u);
}
}
update(u);
}
int main()
{
memset(l,-1,sizeof(l));
memset(r,-1,sizeof(r));
int root = -1;
cin >> n;
int a;
while(n --){
cin >> a;
insert(root,a);
}
cout << e[root] << endl;
return 0;
}
7-37 Hashing (25 分)
#include <iostream>
using namespace std;
const int N = 10010;
int s, n;
int h[N];
bool is_prime(int x)
{
if (x == 1) return false;
for (int i = 2; i * i <= x; i ++ )
if (x % i == 0)
return false;
return true;
}
int find(int x)
{
int t = x % s;
for (int k = 0; k < s; k ++ )
{
int i = (t + k * k) % s;
if (!h[i]) return i;
}
return -1;
}
int main()
{
cin >> s >> n;
while (!is_prime(s)) s ++ ;
for (int i = 0; i < n; i ++ )
{
int x;
cin >> x;
int t = find(x);
if (t == -1) printf("-");
else
{
h[t] = x;
printf("%d", t);
}
if (i != n - 1) printf(" ");
}
return 0;
}
7-38 Hashing - Hard Version (30 分)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;
const int maxn=1010;
const int inf=999999;
vector<int> indegree;
bool visit[maxn];
int e[maxn][maxn];
int a[maxn];
int count[maxn];
int n,cnt;
void topSort(){ //拓扑排序
queue<int> q;
for(int i=0;i<n;i++){
int u=-1,min=inf;
for(int j=0;j<n;j++){
if(visit[j]==false&&!indegree[j])
if(a[j]<min){ //每次都选取最小的入队(其实用数组输出也一样)
min=a[j];
u=j;
}
}
if(u==-1) break;
visit[u]=true;
q.push(a[u]);
for(int v=0;v<n;v++){
if(visit[v]==false&&e[u][v]){
e[u][v]=0;
indegree[v]--;
}
}
}
int flag=0;
while(!q.empty()){ //输出
if(q.front()!=-1){
if(!flag){
cout<<q.front();
q.pop();
flag=1;
}else{
cout<<" ";
cout<<q.front();
q.pop();
}
}else{
q.pop();
}
}
}
int main()
{
fill(e[0],e[0]+maxn*maxn,0);
cin>>n;
cnt=n;
indegree.resize(n);
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n;i++){
if(a[i]==-1) continue;
int index=a[i]%n;
if(index!=i){
indegree[i]=(i-index+n)%n; //计算入度
for(int j=0;j<indegree[i];j++)
e[(index+j)%n][i]=1; //计算连通的边
}
}
topSort();
return 0;
}
7-39 妈妈再也不用担心我被拖库啦! (25 分)
#include<iostream>
#include<string>
#include<map>
using namespace std;
struct Node{
string c; //操作符记录
string zh; //账号
string mm; //密码
string hx; //密码所对应的哈希值
};
int n;
Node node[1005];
map<string,pair<string,string> > mp;//已注册账号信息存储,map中第一个参数为账号,第二个参数为pair型,pair中第一个参数为密码,第二个参数为密码对应的哈希值。
char small_Hash(string str){ //计算字串的哈希值,返回一个字符char
int sum=0;
for(int i=0;i<str.length();i++){
if(str[i]>='A'&&str[i]<='Z') str[i]=str[i]|32;
if(str[i]>='0'&&str[i]<='9'){
sum+=str[i]-'0';
}else{
sum+=str[i]-'a'+10;
}
}
//cout<<"sum:"<<sum<<endl;
sum=sum%36;
if(sum<10) return sum+'0';
else return sum-10+'a';
}
string Hash(string str){ //计算密码的哈希值,返回四位字符串
string hx="0000";
int l=str.length();
int index[5]={0};
for(int i=0;i<l%4;i++){
index[i]++;
}
int j=0;
for(int i=0;i<4;i++){
index[i]+=l/4;
string str1=str.substr(j,index[i]);
//cout<<"str1:"<<i<<":"<<str1<<endl;
j+=index[i];
char h=small_Hash(str1);
hx[i]=h;
}
return hx;
}
int main(void){
cin>>n;
for(int i=0;i<n;i++){
cin>>node[i].c>>node[i].zh>>node[i].mm;
node[i].hx=Hash(node[i].mm);
//cout<<node[i].hx<<endl;
if(node[i].c=="R"){
if(mp.find(node[i].zh)!=mp.end())cout<<"Repeated!"<<endl;
else {
mp[node[i].zh].first=node[i].mm;
mp[node[i].zh].second=node[i].hx;
cout<<"Signed!"<<endl;
}
}else if(node[i].c=="L"){
if(mp.find(node[i].zh)==mp.end()){
cout<<"Failed!"<<endl;
}else{
if(mp.find(node[i].zh)->second.first==node[i].mm) cout<<"Success!"<<endl;
else{
//cout<<mp.find(node[i].zh)->second.second<<" "<<node[i].hx<<endl;
if(mp.find(node[i].zh)->second.second==node[i].hx)cout<<"Attention!"<<endl;
else cout<<"Failed!"<<endl;
}
}
}
}
return 0;
}
//int main(void){ //检验字串哈希值计算
// string str="sdf";
// cout<<small_Hash(str);
// return 0;
//}
7-40 Self-printable B+ Tree (35 分)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node {
struct node* left;
int val[3]; //for nonleaf node, val[0] is the least key among its or its des' leaves
struct node* mid;
struct node* right;
bool isleaf;
int val_num;
int ptr_num;
} Node;
typedef struct bptree {
struct node* root;
struct node* leaves;
} BpTree;
#define MAXKEYN 10005
#define EMP -1
Node* stack[MAXKEYN];
Node** stackptr = stack - 1;
bool push(Node* p) {
if (stackptr == stack + MAXKEYN)return false;
*(++stackptr) = p;
return true;
}
Node* pop() {
if (stackptr == stack - 1)return NULL;
else return *(stackptr--);
}
Node* queue[MAXKEYN];
int front = 0;
int rear = -1;
bool EmptyQueue() {
if (front == (rear + 1) % MAXKEYN)return true;
else return false;
}
bool enqueue(Node* p) {
if (front == (rear + 2) % MAXKEYN)return false;
queue[++rear] = p;
return true;
}
Node* dequeue() {
if (EmptyQueue())return NULL;
else return queue[front++];
}
void Arrange3(int a, int b, int c, Node* p) {
int t;
if (a < b) { t = a; a = b; b = t; }
if (a < c) { t = a; a = c; c = t; }
if (b < c) { t = b; b = c; c = t; }
p->val[0] = c; p->val[1] = b; p->val[2] = a;
}
void Arrange4(int a, int b, int c, int d, Node* p, Node* q) {
int t;
if (a < b) { t = a; a = b; b = t; }
if (a < c) { t = a; a = c; c = t; }
if (a < d) { t = a; a = d; d = t; }
if (b < c) { t = b; b = c; c = t; }
if (b < d) { t = b; b = d; d = t; }
if (c < d) { t = c; c = d; d = t; }
p->val[0] = d; p->val[1] = c; q->val[0] = b; q->val[1] = a;
}
void InternalArrange3(Node* a, Node* b, Node* c, Node* par) {
Node* t;
if (a->val[0] < b->val[0]) { t = a; a = b; b = t; }
if (a->val[0] < c->val[0]) { t = a; a = c; c = t; }
if (b->val[0] < c->val[0]) { t = b; b = c; c = t; }
par->left = c; par->mid = b; par->right = a;
}
void InternalArrange4(Node* a, Node* b, Node* c, Node* d, Node* par1, Node* par2) {
Node* t;
if (a->val[0] < b->val[0]) { t = a; a = b; b = t; }
if (a->val[0] < c->val[0]) { t = a; a = c; c = t; }
if (a->val[0] < d->val[0]) { t = a; a = d; d = t; }
if (b->val[0] < c->val[0]) { t = b; b = c; c = t; }
if (b->val[0] < d->val[0]) { t = b; b = d; d = t; }
if (c->val[0] < d->val[0]) { t = c; c = d; d = t; }
par1->left = d; par1->mid = c; par2->left = b; par2->mid = a;
}
bool Insert(int x, BpTree* tree_add);
bool InternalInsert(Node* new_child, Node* cur_node, BpTree* tree_add);
Node* Search(int x, BpTree tree);
int main(void)
{
int n;
scanf("%d", &n);
int key[MAXKEYN] = { 0 };
for (int i = 0; i < n; i++) {
scanf("%d", &key[i]);
}
BpTree tree;
tree.leaves = NULL;
tree.root = NULL;
for (int i = 0; i < n; i++) {
if (!Insert(key[i], &tree))
printf("Key %d is duplicated\n", key[i]);
}
int cnt = 1, node_num = 0; // level order travesal
Node* T;
enqueue(tree.root);
while (!EmptyQueue()) {
T = dequeue();
printf("[");
if (T->isleaf) { // is leaf, i from 0 to val_num-1
for (int i = 0; i < T->val_num; i++) {
if (i == T->val_num - 1)printf("%d", T->val[i]);
else printf("%d,", T->val[i]);
}
}
else { // is internal node, i from 1 to ptr_num-1
for (int i = 1; i < T->ptr_num; i++) {
if (i == T->ptr_num - 1)printf("%d", T->val[i]);
else printf("%d,", T->val[i]);
}
}
printf("]");
node_num += T->ptr_num; //输出一个点后 node_num加上其子节点数 目的是得到下一层的节点个数
cnt--;
if (cnt == 0 /* && !T->isleaf */) { // after outputting a level, need an enter
printf("\n"); // but there's no enter at the end
cnt = node_num; //输出完一层后 cnt将从node_num开始递减 以确定下一层要输出多少个节点
node_num = 0; //node_num归零 以准备记录下下层的节点数
}
if (T->ptr_num >= 1) enqueue(T->left);
if (T->ptr_num >= 2) enqueue(T->mid);
if (T->ptr_num == 3) enqueue(T->right);
}
return 0;
}
bool Insert(int x, BpTree *tree_add)
{
// if tree is empty
if ((*tree_add).root == NULL) {
(*tree_add).root = (*tree_add).leaves = (Node*)malloc(sizeof(Node));
(*tree_add).root->isleaf = true;
(*tree_add).root->val[0] = x;
(*tree_add).root->val[1] = (*tree_add).root->val[2] = EMP;
(*tree_add).root->val_num = 1;
(*tree_add).root->left = (*tree_add).root->mid = (*tree_add).root->right = NULL;
(*tree_add).root->ptr_num = 0;
return true;
}
//if x already exists
Node* pos = Search(x, (*tree_add));
if (pos) return false;
//insert x
// find the node where x should be
Node* p = (*tree_add).root;
while (!p->isleaf) {
if (p->ptr_num == 2) { // cur node has 1 sepa, stored in val1
if (x < p->val[1]) { push(p); p = p->left; }
else { push(p); p = p->mid; }
}
if (p->ptr_num == 3) { // cur node has 2 sepa, stored in val1 and val2
if (x < p->val[1]) { push(p); p = p->left; }
else if (x >= p->val[1] && x < p->val[2]) { push(p); p = p->mid; }
else { push(p); p = p->right; }
}
}
// now, p points to the leaf node which x belongs to
if (p->val_num == 1) { // no need to split
int t = p->val[0];
p->val[0] = t > x ? x : t;
p->val[1] = t > x ? t : x;
p->val[2] = EMP;
p->val_num++;
}
else if (p->val_num == 2) { // no need to split
Arrange3(p->val[0], p->val[1], x, p);
p->val_num++;
}
else { // need to split
Node* q = (Node*)malloc(sizeof(Node));
q->isleaf = true;
q->left = q->mid = q->right = NULL;
q->ptr_num = 0;
q->right = p->right; p->right = q; // insert q into the linked list of leaves
Arrange4(p->val[0], p->val[1], p->val[2], x, p, q);
p->val_num = q->val_num = 2;
Node* parent = pop();
if (parent == NULL) {
Node* newroot = (Node*)malloc(sizeof(Node));
newroot->isleaf = false;
newroot->val[0] = p->val[0];
newroot->val[1] = q->val[0];
newroot->val[2] = EMP;
newroot->val_num = 2;
newroot->left = p;
newroot->mid = q;
newroot->right = NULL;
newroot->ptr_num = 2;
(*tree_add).root = newroot;
}
else {
InternalInsert(q, parent, tree_add);
}
}
// update the vals of x's ancestors
Node* ances;
while (ances = pop()) {
if (ances->ptr_num >= 1) ances->val[0] = ances->left->val[0];
if (ances->ptr_num >= 2) ances->val[1] = ances->mid->val[0];
if (ances->ptr_num == 3) ances->val[2] = ances->right->val[0];
}
return true;
}
// new_node is generated by cur_node splitting
bool InternalInsert(Node* new_child, Node* cur_node, BpTree *tree_add)
{
if (cur_node->ptr_num == 1) { // impossible to have just 1 ptr
}
else if (cur_node->ptr_num == 2) { // no need to split
InternalArrange3(cur_node->left, cur_node->mid, new_child,
cur_node);
cur_node->ptr_num++;
// update the sepa
cur_node->val[0] = cur_node->left->val[0];
cur_node->val[1] = cur_node->mid->val[0];
cur_node->val[2] = cur_node->right->val[0];
}
else { // need to split
Node* new_node = (Node*)malloc(sizeof(Node));
new_node->isleaf = false;
new_node->left = new_node->mid = new_node->right = NULL;
new_node->ptr_num = 0;
InternalArrange4(cur_node->left, cur_node->mid, cur_node->right, new_child,
cur_node, new_node);
cur_node->ptr_num = new_node->ptr_num = 2;
// update the sepa
cur_node->val[0] = cur_node->left->val[0];
cur_node->val[1] = cur_node->mid->val[0];
cur_node->val[2] = EMP;
new_node->val[0] = new_node->left->val[0];
new_node->val[1] = new_node->mid->val[0];
new_node->val[2] = EMP;
Node* parent = pop();
if (parent == NULL) { // recursion end (cur_node is root)
Node* newroot = (Node*)malloc(sizeof(Node));
newroot->isleaf = false;
newroot->val[0] = cur_node->val[0];
newroot->val[1] = new_node->val[0];
newroot->val[2] = EMP;
newroot->val_num = 2;
newroot->left = cur_node;
newroot->mid = new_node;
newroot->right = NULL;
newroot->ptr_num = 2;
(*tree_add).root = newroot;
}
else {
InternalInsert(new_node, parent, tree_add);
}
}
return true;
}
Node* Search(int x, BpTree tree)
{
Node* p = tree.leaves;
while (p) {
if (p->val_num >= 1) {
if (p->val[0] == x)return p;
}
if (p->val_num >= 2) {
if (p->val[1] == x)return p;
}
if (p->val_num == 3) {
if (p->val[2] == x)return p;
}
p = p->right;
}
return NULL;
}
7-41 凑零钱 (30 分)
#include <bits/stdc++.h>
using namespace std;
int n,m;
const int N = 1e4 + 10;
int a[N];
bool flag;
vector<int>ans;
void dfs(int sum,int u)
{
if(flag)return;
if(u == n + 1){
return;
}
if(a[u] + sum > m){
return;
}
else if(a[u] + sum == m){
ans.push_back(a[u]);
for(int i = 0;i < ans.size();i ++){
if(i) cout << ' ';
cout << ans[i];
}
flag = true;
return;
}else{
ans.push_back(a[u]);
dfs(a[u] + sum,u + 1);
ans.pop_back();
dfs(sum,u + 1);
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
int sum = 0;
for(int i = 1;i <= n;i ++)
{
cin >> a[i];
sum += a[i];
}
if(sum < m){
cout << "No Solution" << endl;
return 0;
}
sort(a + 1,a + n + 1);
while(a[n] > m){
n --;
}
dfs(0,1);
if(!flag){
cout << "No Solution" << endl;
}
return 0;
}
7-42 矩阵链相乘问题 (20 分)
#include <bits/stdc++.h>
using namespace std;
const int MAX = 1005;
int p[MAX];
int m[MAX][MAX];
int n;
void matrix()
{
int i,j,r,k;
memset(m,0,sizeof(m));
for(r = 2; r<=n; r++)
{
for(i = 1; i<=n-r+1; i++)
{
j = i+r-1;
m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];
for(k = i+1; k<j; k++)
{
int t = m[i][k] +m[k+1][j]+p[i-1]*p[k]*p[j];
if(t<m[i][j])
{
m[i][j] = t;
}
}
}
}
}
int main()
{
cin>>n;
for(int i=0; i<n+1; i++)
cin>>p[i];
matrix();
cout<<m[1][n]<<endl;
return 0;
}
7-43 真实的背包故事 (17 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 110,M = 2100;
int dp[N][M][2];
int w[N],v[N];
int main()
{
int n,m;
cin >> n >> m;
for(int i = 1;i <= n;i ++)
cin >> w[i] >> v[i];
for(int i = 1;i <= n;i ++){
for(int j = 0;j <= m;j ++){
dp[i][j][0] = dp[i - 1][j][0];
dp[i][j][1] = dp[i - 1][j][1];
if(j >= v[i]){
if(dp[i - 1][j - v[i]][0] + w[i] > dp[i - 1][j][0]){
dp[i][j][0] = dp[i - 1][j - v[i]][0] + w[i];
dp[i][j][1] = dp[i - 1][j - v[i]][1] + 1;
}else if(dp[i - 1][j - v[i]][0] + w[i] == dp[i - 1][j][0]){
dp[i][j][1] = min(dp[i - 1][j - v[i]][1] + 1,dp[i][j][1]);
}
}
}
}
cout << dp[n][m][0] << ' ' << dp[n][m][1] << endl;
return 0;
}
7-44 流水作业调度 (10 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 110,M = 2100;
pair<int,int>p[N];
typedef pair<int,int> PII;
int main()
{
int n;
cin >> n;
int s1 = 0,s2 = 0;
vector<PII>v1,v2;
/*
1.分组
2.把first < second 的放入到v1,否则放入v2
*/
for(int i = 1;i <= n;i ++)
{
cin >> p[i].first >> p[i].second;
if(p[i].first < p[i].second){
v1.push_back({p[i].first,p[i].second});
}else{
v2.push_back({p[i].first,p[i].second});
}
}
// v1 随便排序
sort(v1.begin(),v1.end(),[](PII p1,PII p2){
return p1.first < p2.first;
});
// v2 中按照升序排序
sort(v1.begin(),v1.end(),[](PII p1,PII p2){
return p1.second < p2.second;
});
vector<PII>vec;
for(auto &x : v1){
vec.push_back(x);
}
for(auto &x : v2){
vec.push_back(x);
}
s1 += vec[0].first;
s2 += vec[0].first + vec[0].second;
for(int i = 1;i < vec.size();i ++){
s1 += vec[i].first;
if(s1 > s2){
s2 = s1 + vec[i].second;
}else{
s2 = s2 + vec[i].second;
}
}
cout << s1 << ' ' << s2 << endl;
return 0;
}
7-45 月饼 (25 分)
/*
注意k的精度!!!!!!!!!!!
注意k的精度!!!!!!!!!!!
注意k的精度!!!!!!!!!!!
注意k的精度!!!!!!!!!!!
注意k的精度!!!!!!!!!!!
*/
#include <iostream>
#include <cstring>
#include <unordered_map>
#include <algorithm>
using namespace std;
const int N = 1e4+10;
struct Moon{
double weight;
double sale;
double ave;
}moon[N];
int n;
double k;
int main()
{
cin >> n >> k;
for(int i = 0;i < n;i++)
{
cin >> moon[i].weight ;
}
for(int i = 0;i < n;i++)
{
cin >> moon[i].sale;
moon[i].ave = moon[i].sale * 1.0 / moon[i].weight;
}
sort(moon,moon+n,[](Moon m1,Moon m2){
return m1.ave > m2.ave;
});
double sum = 0;
for(int i = 0;i < n;i++)
{
if(moon[i].weight < k)
{
k -= moon[i].weight;
sum += moon[i].sale;
}
else
{
sum += k * 1.0 * moon[i].ave;
break;
}
}
printf("%.2lf\n",sum);
return 0;
}
7-46 加油站之最小加油次数 (15 分)
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int main()
{
int n;
int s,h;
cin >> n;
vector<PII>vec;
for(int i = 0;i < n;i ++){
int a,b;
cin >> a >> b;
vec.push_back({a,b});
}
cin >> s >> h;
sort(vec.begin(),vec.end(),[](PII p1,PII p2){
return p1.first > p2.first;
});
priority_queue<int>heap;
int cnt = 0;
for(int i = 0;i < n;i ++){
while(vec[i].first < s - h){
if(heap.size() == 0){
cout << -1 << endl;
return 0;
}
h += heap.top();
heap.pop();
cnt ++;
}
h = h - (s - vec[i].first);
s = vec[i].first;
heap.push(vec[i].second);
}
cout << cnt << endl;
return 0;
}
7-47 活动选择问题 (25 分)
#include<iostream>
#include<algorithm>
#define MAXN 1000
using namespace std;
struct Goods {
int s;
int e;
}goods[MAXN];
bool comp(Goods a, Goods b)
{
return a.e <= b.e;
}
void input(int n)
{
int i;
for (i = 0; i <n; i++)
cin >> goods[i].s >> goods[i].e; //输入活动开始和结束的时间
}
void select(int n)
{
int sum = -1;
int count = 0;
for (int i = 0; i < n; i++)
{
if (goods[i].s >= sum)
{
count++;
sum = goods[i].e;
}
}
cout << count << endl;//能安排的活动个数
}
int main()
{
int n;//活动的总数
while (cin >> n)
{
if (n == 0)break;
input(n);
sort(goods, goods+n, comp);//按活动结束时间从小到大排序
select(n);
}
return 0;
}
7-48 最小生成树-kruskal (10 分)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e6 + 10;
int n, m, p[N];
void init(){
for (int i = 1; i <= n; i++){
p[i] = i;
}
}
struct Edge{
int x, y, w;
bool operator < (const Edge &W)const
{
return w < W.w;
}
}edges[N];
int Find(int x ){
if (p[x] != x) p[x] = Find(p[x]);
return p[x];
}
int kruskal(){
sort(edges,edges + m);
int res = 0;
int cnt = 0;
init();
for (int i = 0; i < m; i++){
int x = edges[i].x, y = edges[i].y, w = edges[i].w;
if (Find(x) != Find(y)){
p[Find(x)] = Find(y);
cnt ++;
res += w;
}
}
if (cnt < n - 1) return -1;
else return res;
}
int main(){
scanf("%d%d",&n,&m);
for (int i = 0; i < m; i++){
int a, b, c;
scanf("%d%d%d",&edges[i].x,&edges[i].y,&edges[i].w);
}
int t = kruskal();
if (t == -1) puts("impossible");
else printf("%d\n",t);
return 0;
}
7-49 最小生成树-prim (10 分)
#include <cstring>
#include <iostream>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
const int N = 1e6+10, M = 2e6+10;
int n,m;
int p[N];
struct Edge
{
int a, b, w;
bool operator < (const Edge &W)const
{
return w < W.w;
}
}edges[M];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int kruskal()
{
sort(edges, edges + m);
for (int i = 1; i <= n; i ++ ) p[i] = i; // 初始化并查集
int res = 0, cnt = 0;
for (int i = 0; i < m; i ++ )
{
int a = edges[i].a, b = edges[i].b, w = edges[i].w;
a = find(a), b = find(b);
if (a != b)
{
p[a] = b;
res += w;
cnt ++ ;
}
}
return res;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i ++ )
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
edges[i] = {a, b, w};
}
int t = kruskal();
printf("%d\n", t);
return 0;
}
7-50 最优服务次序问题 (10 分)
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n,a[1000];
cin>>n;
int i;
for(i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
int sum=0;
for(i=0;i<n;i++){
sum+=a[i]*(n-i - 1);
}
// cout<<sum/(n*1.0)<<endl;
printf("%.2lf\n",sum*1.0/n);
return 0;
}
7-51 删数问题 (10 分)
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <string>
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
char a[105];
int n;
while(cin >> a >> n)
{
int m=strlen(a);
while(n--)
{
int i=0;
while(i<m-1&&a[i]<=a[i+1])
{
i++;
}
if(i==m-1)
{
m--;
while(n--)
m--;
break;
}
else
{
for(int j=i;j<m-1;j++)
a[j]=a[j+1];
m--;
}
}
for(int i=0;i<m;i++)
printf("%c",a[i]);
cout << endl;
}
return 0;
}
// https://blog.csdn.net/lvshubao1314/article/details/19673953
7-52 求解区间覆盖问题 (10 分)
#include <iostream>
#include <algorithm>
using namespace std;
int a[1000];
int s[1000];
int cmp(int a,int b)
{
return a>b;
}
int main()
{
int n,m;
int len;
int sum;
while(cin>>n>>m)
{
for(int i=0;i<=n-1;i++)
{
cin>>a[i];
}
sort(a,a+n);
len=a[n-1]-a[0]+1;
for(int i=0;i<n-1;i++)//求区间的间隔距离
{
s[i]=a[i+1]-a[i]-1;
}
sort(s,s+n-1,cmp);
sum=len;
for(int i=0;i<m-1;i++)
{
sum=sum-s[i];
}
cout << sum << endl;
}
return 0;
}
// https://blog.csdn.net/baidu_30309461/article/details/48399161
7-53 哈夫曼编码 (30 分)
// HuffmanCodes.cpp : 定义控制台应用程序的入口点。
//
//#include <stdafx.h>
#include <vector>
#include <iostream>
#include <string.h>
using namespace std;
//Huffman树结点类
class Node {
public:
Node() {}
Node(char element, int weight)
:element(element), weight(weight), left(NULL), right(NULL) {}
char element;
int weight;
Node* left = NULL;
Node* right = NULL;
bool isleave = false;
};
typedef Node* HFMTree;
//输入测试样例结点类
class Case {
public:
char element;
char route[1000];
int length;
int getlength() {
return strlen(this->route);
}
};
void Read(int num, vector<HFMTree>& minHeap, vector<HFMTree>& inputlist);
void Insert(vector<HFMTree>& minHeap, HFMTree node); //插入数据创建最小堆
HFMTree CreateHFMT(vector<HFMTree>& minHeap); //根据最小堆创建Huffman树
HFMTree DeleteMinHeap(vector<HFMTree>& minHeap); //从最小堆中取出最小元素,删除该结点并重新调整最小堆,最后删除该结点
int getHFMLength(HFMTree hfmtree, int depth); //获得该树编码长度
void Input(vector<Case>& testcase, int num);
bool isOptimalLen(vector<Case>& testcase, vector<HFMTree>& inputlist, int weight); //检查是否符合最优编码长度
bool isPrefixCode(vector<Case>& testcase); //检查是否符合前缀码编码
int main()
{
/*根据输入序列建立Huffman树,并获得最优编码长度*/
int num;
cin >> num;
vector<HFMTree> minHeap; //创建最小堆,用最小堆对序列进行存储
vector<HFMTree> inputlist; //记录输入顺序与权值大小
HFMTree flag = new Node('-', -1);
minHeap.push_back(flag);
Read(num, minHeap, inputlist);
HFMTree hfmtree; //利用最小堆创建Huffman树
hfmtree = CreateHFMT(minHeap);
int optcodelength = getHFMLength(hfmtree, 0); //通过序列创建的Huffman树获得最优编码长度
/*对提交数据进行检查:1.是否符合最优编码长度,2.是否符合无歧义解码规则(前缀码编码,数据仅存在于二叉树叶节点)*/
int count;
cin >> count;
for (int i = 0;i < count;i++) {
vector<Case> testcase;
Input(testcase, num);
bool isoptimallen = isOptimalLen(testcase, inputlist, optcodelength);
bool isprefixcode = isPrefixCode(testcase);
if (isoptimallen && isprefixcode) {
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}
}
system("pause");
return 0;
}
void Read(int num, vector<HFMTree>& minHeap, vector<HFMTree>& inputlist) {
char element;
int weight;
for (int i = 0; i < num; i++) {
cin >> element >> weight;
HFMTree node = new Node(element, weight);
inputlist.push_back(node);
Insert(minHeap, node);
}
//minHeap.erase(minHeap.begin());
}
void Insert(vector<HFMTree>& minHeap, HFMTree node) {
int index = minHeap.size();
minHeap.push_back(node);
//每次插入后自底向上进行调整
while ((*minHeap[index / 2]).weight > (*node).weight) {
//此处不可单纯进行值交换,需要交换两个对象
//(*minHeap[index]).element = (*minHeap[index / 2]).element;
//(*minHeap[index]).weight = (*minHeap[index / 2]).weight;
minHeap[index] = minHeap[index / 2];
index /= 2;
}
minHeap[index] = node;
}
HFMTree CreateHFMT(vector<HFMTree>& minHeap) {
HFMTree hfmtree = new Node();
int size = minHeap.size() - 1;
//进行size-1次合并
for (int i = 1; i < size; i++) {
HFMTree node = new Node();
//每次从最小堆中取出堆顶的两个结点作为该结点的左右子结点
node->left = DeleteMinHeap(minHeap);
node->right = DeleteMinHeap(minHeap);
node->weight = node->left->weight + node->right->weight;
//将该结点作为根节点的二叉树重新加入最小堆
Insert(minHeap, node);
}
//从最小堆中取出建好的Huffman树
hfmtree = DeleteMinHeap(minHeap);
return hfmtree;
}
HFMTree DeleteMinHeap(vector<HFMTree>& minHeap) {
//检查是否堆空
if (minHeap.size() == 1) {
return NULL;
}
//将该堆最大元素装入新结点并返回
HFMTree node = new Node();
node = minHeap[1];
//重新调整该堆
int size = minHeap.size();
int parent, child;
//用最大堆中最后一个元素从根结点开始向上过滤下层结点
HFMTree cmp = new Node();
cmp = minHeap[size - 1];
//从根节点开始,用parent记录根结点下标,用child记录其最小子结点下标,每次循环将parent更新为上一次循环的child
//当parent指向底层结点时跳出循环(会有极端情况比如偏向一边的堆使得parent最终并非指向该子树底层结点,但不影响结果)
for (parent = 1; 2 * parent < size; parent = child) {
child = parent * 2;
//若该子结点不是堆尾结点,令child指向左右子结点中的较小者
if ((child != size - 1) && ((*minHeap[child]).weight > (*minHeap[child + 1]).weight)) {
child++;
}
//当循环到堆尾结点值小于等于该子结点值时,可以结束(此时堆尾结点会替换parent结点而不是child结点)
if (cmp->weight <= (*minHeap[child]).weight) {
break;
}
else {
minHeap[parent] = minHeap[child];
}
}
//将尾结点与当前父结点替换
minHeap[parent] = cmp;
//删除堆尾结点
//此处不能用minHeap.erase(minHeap.end());,因为erase会返回被删除结点的下一结点,而尾结点的下一结点超限
minHeap.pop_back();
//返回该结点
return node;
}
int getHFMLength(HFMTree hfmtree, int depth) {
//若为叶子节点,直接返回其编码长度
if (!hfmtree->left && !hfmtree->right) {
return hfmtree->weight * depth;
}
//否则其他节点一定有两个子树,返回左右子树编码长度之合,深度相应加一
else {
return getHFMLength(hfmtree->left, depth + 1) + getHFMLength(hfmtree->right, depth + 1);
}
}
void Input(vector<Case>& testcase, int num) {
for (int i = 0;i < num;i++) {
Case inputcase;
cin >> inputcase.element >> inputcase.route;
inputcase.length = inputcase.getlength();
testcase.push_back(inputcase);
}
}
bool isOptimalLen(vector<Case>& testcase, vector<HFMTree>& inputlist, int weight) {
int testweight = 0;
for (int i = 0;i < testcase.size();i++) {
testweight += (testcase[i].length * (*inputlist[i]).weight);
}
if (testweight == weight) {
return true;
}
else {
return false;
}
}
bool isPrefixCode(vector<Case>& testcase) {
bool isprefixcode = true;
HFMTree newtree = new Node();
//两种情况验证不满足前缀码要求:1.后创建的分支经过或超过已经被定义的叶子结点,2.后创建分支创建结束时未达到叶子结点
for (int i = 0;i < testcase.size();i++) {
HFMTree point = newtree;
if (isprefixcode == false)break;
for (int j = 0;j < testcase[i].length;j++) {
if (isprefixcode == false)break;
if (testcase[i].route[j] == '0') {
//先检查左子结点是否存在,若不存在,则创建一个左子结点
if (!point->left) {
HFMTree newnode = new Node();
point->left = newnode;
point = point->left;
//若此时为分支的最后一环,则将该结点定义为叶子结点
if (j == testcase[i].length - 1) {
point->isleave = true;
}
}
//若左子树存在,则先将标记指针移至左子树。
else {
point = point->left;
//若左子树为叶子结点,则不符合要求
if (point->isleave) {
isprefixcode = false;
break;
}
//若此时为分支的最后一环且仍有叶子结点,则不符合要求
if ((j == testcase[i].length - 1) && (point->left || point->right)) {
isprefixcode = false;
break;
}
}
}
else if (testcase[i].route[j] == '1') {
//先检查右子结点是否存在,若不存在,则创建一个右子结点
if (!point->right) {
HFMTree newnode = new Node();
point->right = newnode;
point = point->right;
//若此时为分支的最后一环,则将该结点定义为叶子结点
if (j == testcase[i].length - 1) {
point->isleave = true;
}
}
//若左子树存在,则先将标记指针移至左子树。
else {
point = point->right;
//若左子树为叶子结点,则不符合要求
if (point->isleave) {
isprefixcode = false;
break;
}
//若此时为分支的最后一环且仍有叶子结点,则不符合要求
if ((j == testcase[i].length - 1) && (point->left || point->right)) {
isprefixcode = false;
break;
}
}
}
}
}
return isprefixcode;
}
7-54 最短路径-Dijkstra (15 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6;
typedef pair<int,int> pii;
int n,m;
int h[N],ne[N],e[N],w[N],idx;
int dist[N];
bool st[N];
void add(int a,int b,int c)
{
e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx ++ ;
}
void dijkstra(int s)
{
memset(dist,0x3f,sizeof dist);
dist[s] = 0;
priority_queue<pii,vector<pii>,greater<pii> > heap;
heap.push({0,s});
while(heap.size())
{
auto t = heap.top();
heap.pop();
int u = t.second;
if(st[u]) continue;
st[u] = true;
for (int i = h[u] ; i != -1 ; i = ne[i])
{
int p = e[i];
if(dist[p] > dist[u] + w[i])
{
dist[p] = dist[u] + w[i];
heap.push({dist[p],p});
}
}
}
}
int main()
{
memset(h,-1,sizeof h);
int op;
cin >> n >> m >> op;
for (int i = 0 ; i < m ; i ++ )
{
int x,y,z;
cin >> x >> y >> z;
add(x,y,z);
if(!op){
add(y,x,z);
}
}
int s;
cin >> s;
dijkstra(s);
for(int i = 1;i <= n;i ++){
if(dist[i] == 0x3f3f3f3f){
printf("%d->%d:no path\n",s,i);
}else{
printf("%d->%d:%d\n",s,i,dist[i]);
}
}
return 0;
}
7-55 最优二叉搜索树 (10 分)
#include <bits/stdc++.h>
using namespace std;
double b[15], a[15], m[15][15], w[15][15];
int s[15][15], n, MAX = 0x3f3f3f3f, tr[1025];
void obst() {
for (int i = 0; i <= n + 1; ++i) {
m[i][i - 1] = 0.0;
w[i][i - 1] = a[i - 1];
}
for (int l = 1; l <= n; ++l) {
for (int i = 1; i <= n - l + 1; ++i) {
int j = i + l - 1;
int i1 = s[i][j - 1] > i ? s[i][j - 1] : i;
int j1 = s[i + 1][j] > i ? s[i + 1][j] : j;
m[i][j] = (double)MAX;
w[i][j] = w[i][j - 1] + b[j] + a[j];
for (int r = i1; r <= j1; ++r) {
double t = m[i][r - 1] + m[r + 1][j] + w[i][j];
if (t <= m[i][j]) m[i][j] = t, s[i][j] = r;
}
}
}
}
void getTree(int i, int j, int root) {
tr[root] = s[i][j];
if (i >= j) return;
getTree(i, s[i][j] - 1, root << 1);
getTree(s[i][j] + 1, j, root << 1 | 1);
}
void preOrder(int root) {
if (tr[root] == 0) {
printf(". ");
return;
}
printf("%d ", tr[root]);
preOrder(root << 1);
preOrder(root << 1 | 1);
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%lf", &b[i]);
for (int i = 0; i <= n; ++i) scanf("%lf", &a[i]);
obst();
printf("%.2f\n", m[1][n]);
getTree(1, n, 1);
preOrder(1);
return 0;
}
7-56 最长递增子序列 (30 分)
#include <bits/stdc++.h>
using namespace std;
const int N = 2510;
int a[N];
int dp[N];
int main()
{
int n;
cin >> n;
for(int i = 1;i <= n;i ++)
cin >> a[i];
int ans = 0;
for(int i = 1;i <= n;i ++){
dp[i] = 1;
for(int j = 1;j < i;j ++){
if(a[i] > a[j])
dp[i] = max(dp[j] + 1,dp[i]);
ans = max(ans,dp[i]);
}
}
cout << ans << endl;
return 0;
}
7-57 最小费用流 (100 分)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=100010;
bool vis[maxn];
int n,m,s,t,x,y,z,f,dis[maxn],pre[maxn],last[maxn],flow[maxn],maxflow,mincost;
//dis最小花费;pre每个点的前驱;last每个点的所连的前一条边;flow源点到此处的流量
struct Edge{
int to,next,flow,dis;//flow流量 dis花费
}edge[maxn];
int head[maxn],num_edge;
queue <int> q;
void add_edge(int from,int to,int flow,int dis)
{
edge[++num_edge].next=head[from];
edge[num_edge].to=to;
edge[num_edge].flow=flow;
edge[num_edge].dis=dis;
head[from]=num_edge;
}
bool spfa(int s,int t)
{
memset(dis,0x7f,sizeof(dis));
memset(flow,0x7f,sizeof(flow));
memset(vis,0,sizeof(vis));
q.push(s); vis[s]=1; dis[s]=0; pre[t]=-1;
while (!q.empty())
{
int now=q.front();
q.pop();
vis[now]=0;
for (int i=head[now]; i!=-1; i=edge[i].next)
{
if (edge[i].flow>0 && dis[edge[i].to]>dis[now]+edge[i].dis)//正边
{
dis[edge[i].to]=dis[now]+edge[i].dis;
pre[edge[i].to]=now;
last[edge[i].to]=i;
flow[edge[i].to]=min(flow[now],edge[i].flow);//
if (!vis[edge[i].to])
{
vis[edge[i].to]=1;
q.push(edge[i].to);
}
}
}
}
return pre[t]!=-1;
}
void MCMF()
{
while (spfa(s,t))
{
int now=t;
maxflow+=flow[t];
mincost+=flow[t]*dis[t];
while (now!=s)
{//从源点一直回溯到汇点
edge[last[now]].flow-=flow[t];//flow和dis容易搞混
edge[last[now]^1].flow+=flow[t];
now=pre[now];
}
}
}
int main()
{
memset(head,-1,sizeof(head)); num_edge=-1;//初始化
scanf("%d%d",&n,&m);
s = 1,t = n;
for (int i=1; i<=m; i++)
{
scanf("%d%d%d%d",&x,&y,&z,&f);
add_edge(x,y,z,f); add_edge(y,x,0,-f);
//反边的流量为0,花费是相反数
}
MCMF();
printf("%d %d",maxflow,mincost);
return 0;
}
// https://www.luogu.com.cn/problem/solution/P3381
7-58 最大流 加强版 (200 分)
#include<bits/stdc++.h>
#define RIT register int
#define up(l,r,i) for(RIT i=l;i<=r;++i)
#define lw(l,r,i) for(RIT i=l;i>=r;--i)
#define erg(u) for(RIT i=head[u];i;i=nxt[i])
using namespace std;
const int INF =2147483647;
const int MAXN = 1200+3,MAXM =120000+3;
int n,m,s,t,mxflow,cnt;
bool inque[MAXN];
int lft[MAXN],gap[MAXN],ht[MAXN];
int ver[MAXM*2],head[MAXM*2],nxt[MAXM*2],val[MAXM*2],tot=1;
inline int qread(){
RIT ret,c;
while((c=getchar())> '9'||c< '0');
ret=c-'0';
while((c=getchar())>='0'&&c<='9')
ret=ret*10+c-'0';
return ret;
}
inline void add(){
RIT u=qread(),v=qread(),k=qread();
ver[++tot]=v,nxt[tot]=head[u],head[u]=tot,val[tot]=k;
ver[++tot]=u,nxt[tot]=head[v],head[v]=tot,val[tot]=0;
}
inline void bfs(){
queue<int> q;
for(q.push(t),ht[t]=0,inque[t]=true;!q.empty();){
RIT u=q.front(),v;inque[u]=false,q.pop();
erg(u)if(ht[v=ver[i]]>ht[u]+1&&val[i^1]&&!inque[v])
ht[v]=ht[u]+1,q.push(v),inque[v]=true;
}
up(1,n,i) if(ht[i]!=INF) gap[ht[i]]++;
}
inline void update(int u){
ht[u]=INF;
erg(u)if(ht[u]>1+ht[ver[i]]&&val[i])ht[u]=ht[ver[i]]+1;
}
struct cmp{
inline bool operator () (int a,int b) const{
return ht[a]<ht[b];}
};
inline int HIPP(){
up(1,n,i) ht[i]=INF;bfs();
if(ht[s]==INF) return 0;
priority_queue<int,vector<int>,cmp> pq;
erg(s){
lft[ver[i]]+=val[i],swap(val[i^1],val[i]);
if(ver[i]!=t&&ver[i]!=s&&!inque[ver[i]])
pq.push(ver[i]),inque[ver[i]]=true;
}
for(ht[s]=n;!pq.empty();){
RIT u=pq.top(),v;
inque[u]=false,pq.pop();
for(RIT i=head[u];i&&lft[u];i=nxt[i]){
if(!val[i]||ht[v=ver[i]]>=ht[u]) continue;
RIT mn=min(lft[u],val[i]);
lft[u]-=mn,val[i]-=mn,val[i^1]+=mn,lft[v]+=mn;
if(!inque[v]&&v!=s&&v!=t) pq.push(v),inque[v]=true;
}
if(!lft[u]) continue;
if(!(--gap[ht[u]])) up(1,n,i)
if(i!=s&&i!=t&&ht[i]>ht[u]&&ht[i]<n+1) ht[i]=n+1,cnt++;
update(u),++gap[ht[u]],pq.push(u),inque[u]=true;
if(cnt==n) return lft[t];
}
return lft[t];
}
int main(){
n=qread(),m=qread(),s=qread(),t=qread();
up(1,m,i) add();
printf("%d",HIPP());
return 0;
}
// https://www.luogu.com.cn/problem/solution/P4722
7-59 搭配飞行员 (100 分)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110, M = 5210, INF = 1e8;
int m, n, S, T;
int h[N], e[M], f[M], ne[M], idx;
int q[N], d[N], cur[N];
void add(int a, int b, int c)
{
e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}
bool bfs()
{
int hh = 0, tt = 0;
memset(d, -1, sizeof d);
q[0] = S, d[S] = 0, cur[S] = h[S];
while (hh <= tt)
{
int t = q[hh ++ ];
for (int i = h[t]; ~i; i = ne[i])
{
int ver = e[i];
if (d[ver] == -1 && f[i])
{
d[ver] = d[t] + 1;
cur[ver] = h[ver];
if (ver == T) return true;
q[ ++ tt] = ver;
}
}
}
return false;
}
int find(int u, int limit)
{
if (u == T) return limit;
int flow = 0;
for (int i = h[u]; ~i && flow < limit; i = ne[i])
{
cur[u] = i;
int ver = e[i];
if (d[ver] == d[u] + 1 && f[i])
{
int t = find(ver, min(f[i], limit - flow));
if (!t) d[ver] = -1;
f[i] -= t, f[i ^ 1] += t, flow += t;
}
}
return flow;
}
int dinic()
{
int r = 0, flow;
while (bfs()) while (flow = find(S, INF)) r += flow;
return r;
}
int main()
{
scanf("%d%d", &n, &m);
S = 0, T = n + 1;
memset(h, -1, sizeof h);
for (int i = 1; i <= m; i ++ ) add(S, i, 1);
for (int i = m + 1; i <= n; i ++ ) add(i, T, 1);
int a, b;
while (cin >> a >> b) add(a, b, 1);
printf("%d\n", dinic());
/*for (int i = 0; i < idx; i += 2)
if (e[i] > m && e[i] <= n && !f[i])
printf("%d %d\n", e[i ^ 1], e[i]);*/
return 0;
}
// https://www.luogu.com.cn/problem/P2756
7-60 数字梯形 (110 分)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1200, M = 4000, INF = 1e8;
int m, n, S, T;
int h[N], e[M], f[M], w[M], ne[M], idx;
int q[N], d[N], pre[N], incf[N];
bool st[N];
int id[40][40], cost[40][40];
void add(int a, int b, int c, int d)
{
e[idx] = b, f[idx] = c, w[idx] = d, ne[idx] = h[a], h[a] = idx ++ ;
e[idx] = a, f[idx] = 0, w[idx] = -d, ne[idx] = h[b], h[b] = idx ++ ;
}
bool spfa()
{
int hh = 0, tt = 1;
memset(d, -0x3f, sizeof d);
memset(incf, 0, sizeof incf);
q[0] = S, d[S] = 0, incf[S] = INF;
while (hh != tt)
{
int t = q[hh ++ ];
if (hh == N) hh = 0;
st[t] = false;
for (int i = h[t]; ~i; i = ne[i])
{
int ver = e[i];
if (f[i] && d[ver] < d[t] + w[i])
{
d[ver] = d[t] + w[i];
pre[ver] = i;
incf[ver] = min(f[i], incf[t]);
if (!st[ver])
{
q[tt ++ ] = ver;
if (tt == N) tt = 0;
st[ver] = true;
}
}
}
}
return incf[T] > 0;
}
int EK()
{
int cost = 0;
while (spfa())
{
int t = incf[T];
cost += t * d[T];
for (int i = T; i != S; i = e[pre[i] ^ 1])
{
f[pre[i]] -= t;
f[pre[i] ^ 1] += t;
}
}
return cost;
}
int main()
{
int cnt = 0;
scanf("%d%d", &m, &n);
S = ++ cnt;
T = ++ cnt;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m + i - 1; j ++ )
{
scanf("%d", &cost[i][j]);
id[i][j] = ++ cnt;
}
// 规则1
memset(h, -1, sizeof h), idx = 0;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m + i - 1; j ++ )
{
add(id[i][j] * 2, id[i][j] * 2 + 1, 1, cost[i][j]);
if (i == 1) add(S, id[i][j] * 2, 1, 0);
if (i == n) add(id[i][j] * 2 + 1, T, 1, 0);
if (i < n)
{
add(id[i][j] * 2 + 1, id[i + 1][j] * 2, 1, 0);
add(id[i][j] * 2 + 1, id[i + 1][j + 1] * 2, 1, 0);
}
}
printf("%d\n", EK());
// 规则2
memset(h, -1, sizeof h), idx = 0;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m + i - 1; j ++ )
{
add(id[i][j] * 2, id[i][j] * 2 + 1, INF, cost[i][j]);
if (i == 1) add(S, id[i][j] * 2, 1, 0);
if (i == n) add(id[i][j] * 2 + 1, T, INF, 0);
if (i < n)
{
add(id[i][j] * 2 + 1, id[i + 1][j] * 2, 1, 0);
add(id[i][j] * 2 + 1, id[i + 1][j + 1] * 2, 1, 0);
}
}
printf("%d\n", EK());
// 规则3
memset(h, -1, sizeof h), idx = 0;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m + i - 1; j ++ )
{
add(id[i][j] * 2, id[i][j] * 2 + 1, INF, cost[i][j]);
if (i == 1) add(S, id[i][j] * 2, 1, 0);
if (i == n) add(id[i][j] * 2 + 1, T, INF, 0);
if (i < n)
{
add(id[i][j] * 2 + 1, id[i + 1][j] * 2, INF, 0);
add(id[i][j] * 2 + 1, id[i + 1][j + 1] * 2, INF, 0);
}
}
printf("%d\n", EK());
return 0;
}
7-61 孤岛营救问题 (60 分)
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 105,M = 12;
typedef pair<int,int> PII;
int g[N][N],key[N],d[N][1<<M];
bool st[N][1<<M];
int n,m,p,k,s;
int dx[] = {0,1,0,-1};
int dy[] = {1,0,-1,0};
queue<PII> q;
int get(int x,int y){
return (x - 1) * m + y;
}
int bfs(){
int t = get(1,1);
q.push({t,key[t]});
st[t][key[t]] = true;
memset(d,0x3f,sizeof d);
d[t][key[t]] = 0;
while(q.size()){
PII u = q.front();
q.pop();
int z = u.first,v = u.second;
for(int i = 0;i < 4;i++){
int x = (z - 1) / m + dx[i] + 1,y = (z - 1) % m + dy[i] + 1;
int v1 = v,z1 = get(x,y);
if(!x || !y || x > n || y > m || !g[z][z1]) continue;
if(g[z][z1] != -1){
if(!(v >> g[z][z1] & 1)) continue;
}
v1 |= key[z1];
if(!st[z1][v1]){
q.push({z1,v1});
st[z1][v1] = true;
d[z1][v1] = d[z][v] + 1;
}
if(z1 == n * m) return d[z1][v1];
}
}
return -1;
}
int main(){
cin>>n>>m>>p;
cin>>k;
int x1,y1,x2,y2,z,z1,z2;
memset(g,-1,sizeof g);
while(k--){
cin>>x1>>y1>>x2>>y2>>z;
z1 = get(x1,y1),z2 = get(x2,y2);
g[z1][z2] = g[z2][z1] = z;
}
cin>>s;
while(s--){
cin>>x1>>y1>>z;
key[get(x1,y1)] |= 1 << z;
}
cout<<bfs()<<endl;
return 0;
}
7-62 前t个组合结果 (25 分)
#include <iostream>
using namespace std;
int n,r,t;
int m;
const int N = 31;
bool st[N];
int a[N];
void dfs(int num,int id)
{
if(m >= t) return;
if(id == r){
for(int i = 0;i < r;i ++){
cout << ' ' << a[i];
}
cout << endl;
m ++;
return;
}
if(num <= 0) return;
a[id] = num;
dfs(num - 1,id + 1);
dfs(num - 1,id);
}
int main()
{
while(cin >> n >> r >> t){
m = 0;
dfs(n,0);
m = 0;
}
return 0;
}
/*
5 4 3 5 4 3
5 4 2
5 4 1
5 3 2
5 3 1
5 2 1
4 3 2
4 3 1
4 2 1
3 2 1
*/
7-63 自然数拆分问题 (60 分)
#include <iostream>
#include <vector>
using namespace std;
int n,r,t;
int m;
const int N = 60;
bool st[N];
int a[N];
vector<int>vec;
void dfs(int num,int s)
{
if(num == 0){
cout << n << "=" << vec[0];
for(int i = 1;i < vec.size();i ++){
cout << "+" << vec[i];
}
cout << endl;
return;
}
for(int i = s;i <= num;i ++){
vec.push_back(i);
dfs(num - i,i);
vec.pop_back();
}
}
int main()
{
ios::sync_with_stdio(false);
cin >> n;
dfs(n,1);
return 0;
}
/*
5 4 3 5 4 3
5 4 2
5 4 1
5 3 2
5 3 1
5 2 1
4 3 2
4 3 1
4 2 1
3 2 1
*/
7-64 字母排列问题 (10 分)
#include <iostream>
#include <vector>
using namespace std;
int n,m;
string str;
bool st[30];
void dfs(int cnt)
{
if(cnt == m){
for(int i = 0;i < m;i ++){
printf("%c",str[i]);
}
printf("\n");
return;
}
for(int i = 0;i < n;i ++){
char c = i + 'A';
if(st[i]) continue;
str = str + c;
st[i] = true;
dfs(cnt + 1);
st[i] = false;
str.pop_back();
}
}
int main()
{
scanf("%d%d",&n,&m);
dfs(0);
return 0;
}
/*
AB
AC
BA
BC
CA
CB
*/
7-65 八皇后问题 (20 分)
#include <stdio.h>
#include <math.h>
int queenPlaces[92][8]; //存放92种皇后棋子的摆放方法
int count = 0;
int board[8][8]; //仿真棋盘
void putQueen(int ithQueen); //递归函数,每次摆好一个棋子
int main()
{
int n, i, j;
for(i = 0; i < 8; i++){ // 初始化
for(j = 0; j < 8; j++)
board[i][j] = -1;
for(j = 0; j < 92; j++)
queenPlaces[j][i] = 0;
}
putQueen(0); //从第0个棋子开始摆放,运行的结果是将queenPlaces生成好
scanf("%d", &n);
for(i = 0; i < n; i++){
int ith;
scanf("%d", &ith);
for(j = 0; j < 8; j++)
printf("%d", queenPlaces[ith - 1][j]);
printf("\n");
}
}
void putQueen(int ithQueen){
int i, k, r;
if(ithQueen == 8){
count ++;
return;
}
for(i = 0; i < 8; i++){
if(board[i][ithQueen] == -1){
//摆放皇后
board[i][ithQueen] = ithQueen;
//将其后所有的摆放方法的第ith个皇后都放在i+1的位置上
//在i增加以后,后面的第ith个皇后摆放方法后覆盖此时的设置
for(k = count; k < 92; k++)
queenPlaces[k][ithQueen] = i + 1;
//设置控制范围
for(k = 0; k < 8; k++)
for(r = 0; r < 8; r++)
if(board[k][r] == -1 &&
(k == i || r == ithQueen || abs(k - i) == abs(r - ithQueen)))
board[k][r] = ithQueen;
//向下级递归
putQueen(ithQueen + 1);
//回溯,撤销控制范围
for(k = 0; k < 8; k++)
for(r = 0; r < 8; r++)
if(board[k][r] == ithQueen) board[k][r] = -1;
}
}
}
7-66 旅行售货员 (10 分)
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int n;
vector<int> path;
const int N = 10;
int g[N][N];
int ans = 0x3f3f3f3f;
void dfs(int u, int state)
{
if (u == n)
{
int sum = 0;
for(int i = 0;i < path.size() - 1;i ++){
sum += g[path[i]][path[i + 1]];
}
sum += g[path[path.size() - 1]][path[0]];
// cout << endl;
ans = min(ans,sum);
return;
}
for (int i = 0; i < n; i ++ )
if (!(state >> i & 1))
{
path.push_back(i + 1);
dfs(u + 1, state + (1 << i));
path.pop_back();
}
}
int main()
{
cin >> n;
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
cin >> g[i][j];
dfs(0, 0);
cout << ans << endl;
return 0;
}