1.山东建筑大学烟台校区启用,现需要为n位同学分配宿舍,假设学校充分尊重同学们的意见,即可以任何x个同学使用一间宿舍(x>0),问:一共有多少种宿舍分配方案?
#include<bits/stdc++.h>
#include <stdio.h>
using namespace std;
long long int f(int n,int m ){
if(n > 0 && m == 0 ||n == 0&& m > 0){
return 0;
}
else if(n == m) {
return 1;
}
else{
return f(n-1 ,m-1) + m*f(n-1 ,m);
}
}
int main(){
int n ,m;
cin>> n;
long long int a[101] = {};
long long int sum = 0;
for(int i = 1;i<=n; i++){
a[i] = f(n ,i);
sum += a[i];
}
cout <<sum<<endl;
return 0;
}
2.考虑下面的应用场景: 山东建筑大学烟台校区启用,现需要为n位同学分配至m间宿舍,问:一共有多少种宿舍分配方案?
#include <bits/stdc++.h>
#include <iostream>
#include <vector>
using namespace std;
int countAllocation(int n, int m) {
vector<vector<int>> dp(n+1, vector<int>(m+1, 0));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (i == j || j == 1) {
dp[i][j] = 1;
} else {
dp[i][j] = j * dp[i-1][j] + dp[i-1][j-1];
}
}
}
return dp[n][m];
}
int main() {
int n, m;
cin >> n >> m;
int result = countAllocation(n, m);
cout << result << endl;
return 0;
}
3.给定一串十进制数字,共n位,要求将这些数字分成m段,由此得到了m个整数。如何划分使得m个整数的乘积最大?
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, p;
cin >> n >> p;
string digits;
cin >> digits;
vector<vector<int>> dp(n + 1, vector<int>(p + 1, 0));
for (int i = 1; i <= n; i++) {
dp[i][1] = dp[i - 1][1] * 10 + (digits[i - 1] - '0');
}
for (int i = 2; i <= n; i++) {
for (int j = 2; j <= p; j++) {
int maxProduct = 0;
for (int k = i - 1; k >= j - 1; k--) {
int currentSegment = stoi(digits.substr(k, i - k));
maxProduct = max(maxProduct, dp[k][j - 1] * currentSegment);
}
dp[i][j] = maxProduct;
}
}
cout << dp[n][p] << endl;
return 0;
}
4.现有一个二维的金字塔,由若干方格组成,每个方格里的数字表明该方格的宝物价值。 你可以选择一条从塔顶到塔底的路线(每层只能走一个方格,该方格必须为上一层走过方格的相邻方格),并收集路线上所有方格的宝物,如何选择路线,使得最终收集到的宝物价值的和最大? '
#include <bits/stdc++.h>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<vector<int>> a(n, vector<int>(n, 0));
for (int i = 0; i < n; ++i) {
for (int j = 0; j <= i; ++j) {
cin >> a[i][j];
}
}
for (int i = n - 2; i >= 0; --i) {
for (int j = 0; j <= i; ++j) {
a[i][j] += max(a[i + 1][j], a[i + 1][j + 1]);
}
}
int max_value = a[0][0];
cout << max_value << endl;
return 0;
}
5. 磁带最优存储问题要求确定这 n 个程序在磁带上的一个存储次序,使平均读取时间达到最小。试设计一个解此问题的算法,并分析算法的正确性和计算复杂性。
#include <bits/stdc++.h>
using namespace std;
int n;
struct node {
int a, b;
}
p[10000];
bool cmp(node a, node b) {
return a.a * a.b < b.a * b.b;
}
int main() {
cin >> n;
int sum = 0;
for (int i = 0; i < n; i++) {
cin >> p[i].a >> p[i].b;
sum += p[i].b;
}
sort(p, p + n, cmp);
double t = 0, tmp = 0;
for (int i = 0; i < n; i++) {
tmp = 0;
for (int j = 0; j <= i; j++) {
tmp += p[j].a * (p[j].b * 1.0 / sum);
}
t += tmp;
}
printf("%.6g\n", t);
return 0;
}
6. 山东建筑大学有足够多的教室,可以安排一学期内的所有课程。当然,教务处希望使用的教室数量越少越好。设计一个有效的贪心算法进行排课。
#include <bits/stdc++.h>
using namespace std;
struct Course {
int start_time;
int end_time;
};
bool compareCourses(const Course& c1, const Course& c2) {
return c1.start_time < c2.start_time;
}
int findMinClassrooms(vector<Course>& courses) {
sort(courses.begin(), courses.end(), compareCourses);
vector<int> end_times;
end_times.push_back(courses[0].end_time);
for (int i = 1; i < courses.size(); i++) {
bool assigned = false;
for (int j = 0; j < end_times.size(); j++) {
if (courses[i].start_time >= end_times[j]) {
end_times[j] = courses[i].end_time;
assigned = true;
break;
}
}
if (!assigned) {
end_times.push_back(courses[i].end_time);
}
}
return end_times.size();
}
int main() {
int n;
cin >> n;
vector<Course> courses(n);
for (int i = 0; i < n; i++) {
cin >> courses[i].start_time >> courses[i].end_time;
}
int min_classrooms = findMinClassrooms(courses);
cout << min_classrooms << endl;
return 0;
}
实验2.1:假设从济南到西藏的路线上共有n个城市1,2,…,n,每个城市都有一个租车公司。你可以在这些城市出租汽车,并在之后的任何一个城市归还汽车。城市i到城市j之间的租金为x(i,j),1≤i<j≤n。试设计一个算法,计算从济南(城市1)到西藏(城市n)所需的最少租金。
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int main(){
int n;
cin>>n;
vector<vector<int>>f(n+1,vector<int>(n+1,0));
vector<int>c(n+1,INT_MAX);
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
cin>>f[i][j];
}
}
c[1]=0;
for(int i=2;i<=n;i++){
c[i]=INT_MAX;
for(int j=1;j<i;j++){
c[i]=min(c[i],c[j]+f[j][i]);
}
}
cout<<c[n]<<endl;
return 0;
}
实验2.2:云天明送给程心一串珍贵的项链,上面共有n颗珍珠,每一颗珍珠上都有一个数字。
每两颗相邻的珍珠可以合并为一颗新的珍珠,合并后这两颗珍珠消失,新珍珠上的数字为合并的两颗的的数字之和。并且此次操作的得分要加上这个和。
经过n-1次这样的合并后,项链只剩下最后一颗珍珠,问总得分的最小值和最大值。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int MAXN = 205;
int pearl[MAXN], sum[MAXN];
int minpearl[MAXN][MAXN], maxpearl[MAXN][MAXN];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> pearl[i];
pearl[i + n] = pearl[i];
}
for (int i = 1; i <= 2 * n; i++) {
sum[i] = sum[i - 1] + pearl[i];
}
for (int len = 2; len <= n; len++) {
for (int i = 1; i <= 2 * n - len + 1; i++) {
int j = i + len - 1;
minpearl[i][j] = INF;
maxpearl[i][j] = 0;
for (int k = i; k < j; k++) {
minpearl[i][j] = min(minpearl[i][j], minpearl[i][k] + minpearl[k + 1][j] + sum[j] - sum[i - 1]);
maxpearl[i][j] = max(maxpearl[i][j], maxpearl[i][k] + maxpearl[k + 1][j] + sum[j] - sum[i - 1]);
}
}
}
int Max = 0, Min = INF;
for (int i = 1; i <= n; i++) {
int j = i + n - 1;
Max = max(Max, maxpearl[i][j]);
Min = min(Min, minpearl[i][j]);
}
cout << Min << endl << Max << endl;
}
实验2.3:对于长度相同的 2 个字符串 A 和 B,其距离定义为相应位置字符距离之和。2 个非空格字符的距离是它们的 ASCII 码之差的绝对值。空格与空格的距离为 0;空格与其它字符的距离为一定值 k。 在一般情况下,字符串 A 和 B 的长度不一定相同。字符串 A 的扩展是在 A 中插入若干空格字符所产生的字符串。在字符串 A 和 B 的所有长度相同的扩展中,有一对距离最小的扩展,该距离称为字符串 A 和 B 的扩展距离。 对于给定的字符串 A 和 B,试设计一个算法,计算其扩展距离。
#include <bits/stdc++.h>
using namespace std;
int dist(char c1, char c2, int k) {
return (c1 == ' ' || c2 == ' ') ? k : abs(c1 - c2);
}
int main() {
string a, b;
cin >> a >> b;
int t;
cin >> t;
int len1 = a.size();
int len2 = b.size();
vector<vector<int> > c(len1 + 1, vector<int>(len2 + 1, 0));
for (int i = 1; i <= len1; i++) {
c[i][0] = t * i;
}
for (int i = 1; i <= len2; i++) {
c[0][i] = t * i;
}
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
c[i][j] = min(c[i - 1][j - 1] + dist(a[i - 1], b[j - 1], t),
min(c[i - 1][j] + t, c[i][j - 1] + t));
}
}
cout << c[len1][len2] << endl;
return 0;
}
实验2.4:现有一对双胞胎,在一个有n * n个方格的方形宝藏区域F中探宝。(i,j)方格中宝物的价值为v(i,j),如下图所示。
双胞胎均从F的A点出发,向下或向右行走,直到B点,在走过的路上,收集方格中的宝藏。试找出兄弟二人可以获得的宝藏总价的值最大。
#include <iostream>
using namespace std;
const int MAX_N = 101;
int a[MAX_N][MAX_N];
int m[MAX_N][MAX_N][MAX_N][MAX_N];
int n;
int max(int a, int b) {
return (a > b) ? a : b;
}
void f(int x1, int y1, int x2, int y2, int t) {
if (x1 == x2 && y1 == y2) {
m[x1][y1][x2][y2] = max(m[x1][y1][x2][y2], t + a[x1][y1]);
} else {
m[x1][y1][x2][y2] = max(m[x1][y1][x2][y2], t + a[x1][y1] + a[x2][y2]);
}
}
void GetList() {
int x1, y1, x2, y2;
m[1][1][1][1] = a[1][1];
int s;
for (s = 2; s <= 2 * n - 1; s++) {
for (x1 = 1; x1 <= s - 1; x1++) {
for (x2 = 1; x2 <= s - 1; x2++) {
y1 = s - x1;
y2 = s - x2;
int t = m[x1][y1][x2][y2];
f(x1 + 1, y1, x2 + 1, y2, t);
f(x1 + 1, y1, x2, y2 + 1, t);
f(x1, y1 + 1, x2 + 1, y2, t);
f(x1, y1 + 1, x2, y2 + 1, t);
}
}
}
}
int main() {
cin >> n;
int x, y, v;
while (cin >> x >> y >> v && (x || y || v)) {
a[x][y] = v;
}
GetList();
cout << m[n][n][n][n] << endl;
return 0;
}
实验2.5:有兄弟二人做n道题目。
已知哥哥做题目i需要时间ai,弟弟做题目i需要时间bi 。
由于兄弟二人对知识掌握的程度不同,很可能对于某些 i,有 ai ≥ bi ,而对于某些 j,j≠i,有 aj < bj 。
每一道题目只能交给二人中的一个来做。
设计一个算法,使得二人解掉所有题目所用的时间最短(从任何一人开始做题到最后一人解掉最后一道题目的总时间)。
研究一个实例: (a1,a2,a3,a4,a5,a6)=(2,5,7,10,5,2);(b1,b2,b3,b4,b5,b6)=(3,8,4,11,3,4)。
#include <iostream>
using namespace std;
const int MAX_N = 1000;
const int MAX_TIME = 10000;
int n;
int aT = 0;
int mintime = MAX_TIME;
int a[MAX_N];
int b[MAX_N];
int c[MAX_N][MAX_TIME];
int T() {
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= aT; j++) {
c[i][j] = MAX_TIME;
}
}
c[0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= aT; j++) {
c[i][j] = c[i - 1][j] + b[i];
if (j >= a[i]) {
c[i][j] = min(c[i][j], c[i - 1][j - a[i]]);
}
}
}
for (int j = 0; j <= aT; j++) {
int t = max(c[n][j], j);
mintime = min(mintime, t);
}
return mintime;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
aT += a[i];
}
for (int i = 1; i <= n; i++) {
cin >> b[i];
}
T();
cout << mintime << endl;
return 0;
}
实验2.6作为一个比赛队伍总教练的你,请解决下面的问题:
你作为总教练的聘期为n天。
在这n天里,一共有n个比赛可以参加。
队员们都愿意参加比赛,而不愿意训练,所以希望有比赛就参加。
如果在某一天有多场比赛同时开始,作为主教练的你可任选其中一场比赛参加(前提是队伍没有正在参加的比赛)。
比赛从第s天开始,持续t天,则该比赛在第 s+t-1 天结束。
作为总教练的你,应该如何选择比赛,才能既使得队员满意
#include <bits/stdc++.h>
using namespace std;
vector<int> a, b, c;
int main() {
int n, x;
cin >> n >> x;
a.resize(n + 2, INT_MAX);
b.resize(x + 1);
c.resize(x + 1);
for (int i = 1; i <= x; i++) {
int y, t;
cin >> y >> t;
b[i] = y;
c[i] = t;
}
int m = 0;
for (int i = n; i >= 1; i--) {
a[n + 1] = n;
for (int j = 1; j <= x; j++) {
if (b[j] == i) {
a[i] = min(a[b[j] + c[j]], a[i]);
m += 1;
}
}
if (m == 0) {
a[i] = a[i + 1] - 1;
}
m = 0;
}
cout << a[1];
return 0;
}
1.1大于 1 的正整数 n 可以分解为:n=x1x2…*xm。对于给定的正整数 n,编程计算 n 共有多少种不同的分解式。
#include <bits/stdc++.h>
using namespace std;
map<int ,int >a;
int f(int n){
if(n == 1)
return 1;
if(a[n])
return a[n];
int curCount=1;
for(int i=2;i<=sqrt(n);i++){
if(n%i == 0){
curCount+=f(i);
if(i!=n/i){
curCount+=f(n/i);
}
}
}
a[n] = curCount;
return a[n];
}
int main()
{
int n;
while(cin>>n){
cout<<f(n)<<endl;
}
}
1.2设 A、B、C 是 3 个塔座。开始时,在塔座 A 上有一叠共 n 个圆盘,这些圆盘自下而上,由大到小地叠在一起。各圆盘从小到大编号为 1,2,……,n,奇数号圆盘着蓝色,偶数号圆盘着红色,如图所示。现要求将塔座 A 上的这一叠圆盘移到塔座 B 上,并仍按同样顺序叠置。在移动圆盘时应遵守以下移动规则: 规则(1):每次只能移动 1 个圆盘; 规则(2):任何时刻都不允许将较大的圆盘压在较小的圆盘之上; 规则(3):任何时刻都不允许将同色圆盘叠在一起; 规则(4):在满足移动规则(1)-(3)的前提下,可将圆盘移至 A,B,C 中任一塔座上。 试设计一个算法,用最少的移动次数将塔座 A 上的 n 个圆盘移到塔座 B 上,并仍按同样顺序叠置。
#include <bits/stdc++.h>
#include<iostream>
using namespace std;
void Hannoi(int,char,char,char);
int main()
{
int n;
cin>>n;
Hannoi(n,'A','B','C');
return 0;
}
void Move(int i,char M,char N)
{
cout<<i<<' '<<M<<' '<<N<<endl;
}
void Hannoi(int n,char W1,char W2,char W3)
{
if(n==1)
{
Move(1,W1,W2);
return;
}
n--;
Hannoi(n,W1,W3,W2);
Move(n+1,W1,W2);
Hannoi(n,W3,W2,W1);
}
1.3给定一个自然数 n,由 n 开始可以依次产生半数集 set(n)中的数如下。 (1) n∈set(n); (2) 在 n 的左边加上一个自然数,但该自然数不能超过最近添加的数的一半; (3) 按此规则进行处理,直到不能再添加自然数为止。 例如,set(6)={6,16,26,126,36,136}。半数集 set(6)中有 6 个元素。 注意半数集是多重集#include <bits/stdc++.h>
using namespace std;
vector<int> a;
int comp(int n)
{
if (n == 0) {
return 0;
}
if (a[n] > 0) {
return a[n];
}
int ans = 1;
for (int i = 1; i <= n / 2; i++) {
ans += comp(i);
}
a[n] = ans;
return ans;
}
int main()
{
int n;
while (cin >> n && n != 0) {
a.resize(n + 1, 0);
a[1] = 1;
cout << comp(n) << endl;
}
return 0;
}。