文件读入与核对
int read(const string& file) {
ifstream ifs;
ifs.open(file.c_str(), ios::in); // 使用 c_str() 将 string 转换为 const char*
int n;
if (ifs >> n) {
ifs.close();
return n;
} else {
// 如果无法读取文件或者无法提取值,则处理错误
cerr << "Error reading from file: " << file << endl;
return -1; // 返回错误代码或者抛出异常
}
}
void write(int a[], const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
for (int i = 0; i < 10; i++) {
ofs << a[i] << endl;
}
ofs.close();
}
void comparejugle(const string& a, const string& b) {
// 使用 .c_str() 将 string 类型的文件路径转换为 const char* 类型
ifstream fileA(a.c_str());
ifstream fileB(b.c_str());
// 检查文件是否正确打开
if (!fileA.is_open() || !fileB.is_open()) {
cerr << "Error opening files." << endl;
return;
}
// 读取文件A和文件B的内容到字符串中
string contentA((istreambuf_iterator<char>(fileA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(fileB)), istreambuf_iterator<char>());
// 比较两个字符串,如果不同则输出 "NO",相同则输出 "Yes"
if (contentA != contentB) {
cout << "NO" << endl;
} else {
cout << "Yes" << endl;
}
// 关闭文件
fileA.close();
fileB.close();
}
string baseFolder = "F:\\桌面\\prog11统计数字问题\\prog11统计数字问题\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\count"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\count"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\count"; // 正确答案文件夹路径
for (int i = 0; i <= 9; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
// cout << s << " " << testFilePath << endl;
n = read(testFilePath);
cout << n << endl;
for (int j = 0; j <= 9; j++) {
a[j] = get(n, j);
cout << a[j] << " ";
}
cout << endl;
string answerFilePath = answerFolder + s + ".txt";
write(a, answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
第二章 、 分治
一、众数问题
先排序然后从中位数向两边找
优化: 当左边的或者右面的待递归集合小于S(中位数的个数)是可以直接return的;
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std ;
int a[10010] ;
int fre ;
int num ;
void mode(int a[] ,int l ,int r){
if(l>=r) return ;
int x = a[l+r>>1] ;
int i =l+r >> 1 ;
int j =l+r >> 1 ;
while(a[i]==x&&i>=l) i-- ;
while(a[j]==x&&j<=r) j++ ;
int s = j-i+1-2 ;
// cout << s<<" " << i << " " << j <<endl ;
if(s>fre) {
fre = s ;
num = x ;
}
mode(a,l,i) ;
mode(a,j,r) ;
}
signed main() {
ios::sync_with_stdio(0) ;
cin.tie(0);
cout.tie(0) ;
int n ;
cin >> n ;
for(int i= 1 ; i <= n ; i++){
cin >> a[i] ;
}
sort(a+1,a+n+1) ;
num = 0 ;
fre = 0 ;
mode(a,1,n) ;
cout << num <<" " << fre ;
return 0;
}
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std ;
int a[10000010] ;
int fre ;
int num ;
int n ;
void read(const string& file) {
ifstream ifs;
ifs.open(file.c_str(), ios::in); // 使用 c_str() 将 string 转换为 const char*
if (ifs >> n) {
for(int i= 1 ;i <=n ;i++) ifs >> a[i] ;
ifs.close();
} else {
// 如果无法读取文件或者无法提取值,则处理错误
cerr << "Error reading from file: " << file << endl;
return ; // 返回错误代码或者抛出异常
}
}
void write(const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << num << endl ;
ofs << fre ;
ofs.close();
}
void comparejugle(const string& a, const string& b) {
// 使用 .c_str() 将 string 类型的文件路径转换为 const char* 类型
ifstream fileA(a.c_str());
ifstream fileB(b.c_str());
// 检查文件是否正确打开
if (!fileA.is_open() || !fileB.is_open()) {
cerr << "Error opening files." << endl;
return;
}
// 读取文件A和文件B的内容到字符串中
string contentA((istreambuf_iterator<char>(fileA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(fileB)), istreambuf_iterator<char>());
// 比较两个字符串,如果不同则输出 "NO",相同则输出 "Yes"
if (contentA != contentB) {
cout << "NO" << endl;
} else {
cout << "Yes" << endl;
}
// 关闭文件
fileA.close();
fileB.close();
}
void mode(int a[] ,int l ,int r){
if(l>=r) return ;
int x = a[l+r>>1] ;
int i =l+r >> 1 ;
int j =l+r >> 1 ;
while(a[i]==x&&i>=l) i-- ;
while(a[j]==x&&j<=r) j++ ;
int s = j-i+1-2 ;
// cout << s<<" " << i << " " << j <<endl ;
if(s>fre) {
fre = s ;
num = x ;
}
mode(a,l,i) ;
mode(a,j,r) ;
}
signed main() {
string baseFolder = "F:\\桌面\\算法设计与分析\\第2章分治策略实验\\第2章分治策略实验包\\prog21众数问题\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\mode"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\mode"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\mode"; // 正确答案文件夹路径
for (int i = 1; i <= 10; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
// cout << s << " " << testFilePath << endl;
read(testFilePath);
sort(a+1,a+n+1) ;
num = 0 ;
fre = 0 ;
mode(a,1,n) ;
string answerFilePath = answerFolder + s + ".txt";
write( answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
!!!!!!!!!!!!!
跑不了的原因竟然是数组开的太小了!!!!!!!!!!!!!
二、半数集问题
s u m + = f o r ( s e t ( i ) − > s e t ( n / 2 ) ) sum+=for(set(i)->set(n/2)) sum+=for(set(i)−>set(n/2))
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std ;
int set1(int k){
int sum = 1 ;
for(int i = 1 ;i <=k/2 ; i++) sum+=set1(i) ;
return sum ;
}
signed main() {
ios::sync_with_stdio(0) ;
cin.tie(0);
cout.tie(0) ;
int n ;
cin >> n ;
cout << set1(n) ;
return 0;
}
三、有重复元素全排列
注意 :交换的时候记得还回去,不然会多很多组合(重复出现的)
需要注意输出在什么地方~!!!
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std ;
char a[10010] ;
int sum ;
int n ;
bool check(int l,int r){
for(int i=l ;i<r ;i++){
if(a[i]==a[r]) return false ;
}
return true ;
}
void sortt(int len , int idx ){
if(len ==idx){
for(int i=1 ;i<=n ;i++) cout <<a[i] << " " ;
cout <<endl ;
sum++ ;
}//需要注意输出在什么地方
else
for(int i = idx ;i<=len ;i++){
if(!check(idx , i)) continue ;
swap(a[i],a[idx]) ;
sortt(len , idx+1) ;
swap(a[i],a[idx]) ;
}
return ;
}
signed main() {
ios::sync_with_stdio(0) ;
cin.tie(0);
cout.tie(0) ;
cin >> n ;
for(int i = 1 ;i<=n ;i++) cin >> a[i] ;
sum = 0;
sortt(n,1);
cout << sum ;
return 0;
}
#include <iostream>
#include <fstream>
#include <string>
#include <bits/stdc++.h>
using namespace std;
char a[10010];
int sum;
int n;
bool check(int l, int r) {
for(int i = l; i < r; i++) {
if(a[i] == a[r]) return false;
}
return true;
}
void sortt(int len, int idx, const string& file) {
ofstream outputFile; // 定义文件输出流
if(len == idx) {
string permutation;
for(int i = 1; i <= n; i++) {
permutation += a[i];
}
// cout << permutation << endl;
outputFile.open(file.c_str(), ios::app); // 以追加模式打开文件
outputFile << permutation << endl; // 写入单个排列并换行
outputFile.close(); // 关闭文件
sum++;
} else {
for(int i = idx; i <= len; i++) {
if(!check(idx, i)) continue;
swap(a[idx], a[i]);
sortt(len, idx + 1, file);
swap(a[idx], a[i]);
}
}
}
int read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n) {
for(int i = 1; i <= n; i++) {
ifs >> a[i];
}
ifs.close();
return n;
} else {
cerr << "读取文件错误:" << file << endl;
return -1;
}
}
void write(int sum, const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << sum ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
} else {
cout << "一致" << endl;
}
}
int main() {
// 替换为你提供的文件路径
string inputFile = "F:\\桌面\\算法设计与分析\\第2章分治策略实验\\第2章分治策略实验包\\prog25有重复元素的排列\\test\\perm3.in";
string outputFile = "F:\\桌面\\算法设计与分析\\第2章分治策略实验\\第2章分治策略实验包\\prog25有重复元素的排列\\myanswer\\ans3.txt";
string answerFile = "F:\\桌面\\算法设计与分析\\第2章分治策略实验\\第2章分治策略实验包\\prog25有重复元素的排列\\answer\\perm3.out";
string baseFolder = "F:\\桌面\\算法设计与分析\\第2章分治策略实验\\第2章分治策略实验包\\prog25有重复元素的排列\\";
string testFolder = baseFolder + "test\\perm"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\ans"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\perm"; // 正确答案文件夹路径
for (int i = 3; i <= 10; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
string answerFilePath = answerFolder + s + ".txt";
// cout << s << " " << testFilePath << endl;
n = read(testFilePath);
sum = 0;
sortt(n, 1, answerFilePath);
ofstream outputFile; // 定义文件输出流
outputFile.open(answerFilePath.c_str(), ios::app); // 以追加模式打开文件
outputFile << sum << endl; // 写入单个排列并换行
outputFile.close(); // 关闭文件*/
cout <<sum <<endl ;
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
四、集合划分
q [ n , m ] = q [ n − 1 , m − 1 ] + m ∗ q [ n − 1 , m ] q[n,m] = q[n-1,m-1]+m*q[n-1,m] q[n,m]=q[n−1,m−1]+m∗q[n−1,m] ;
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std ;
int q(int n , int m){
if(n==1) return 1 ;
if(m>n||n==0||m==0) return 0 ;
if(m==1||n==m) return 1 ;
int res = q(n-1,m-1) + m*q(n-1,m) ;
return res ;
}
signed main() {
ios::sync_with_stdio(0) ;
cin.tie(0);
cout.tie(0) ;
int n ,m ;
cin >> n >> m;
int res = q(n,m) ;
cout << res ;
return 0;
}
五、整数因式分解
d a t a ( n ) + = d a t a ( n / [ 2 − > n ] ) data(n)+=data(n/[2->n]) data(n)+=data(n/[2−>n]) ;
d a t a ( 1 ) = 1 data(1) = 1 data(1)=1
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std ;
int res ;
void data(int n){
if(n==1) {
res++;
}
for(int i=2 ; i<=n ; i++){
if(n%i==0)
data(n/i) ;
}
}
signed main() {
ios::sync_with_stdio(0) ;
cin.tie(0);
cout.tie(0) ;
int n ;
cin >> n ;
res = 0 ;
data(n) ;
cout << res <<endl ;
return 0;
}
第三章 、 动态规划
一、独立任务最优调度问题
难点 : 找到状态方程本问题的是 i 代表第几个任务 j 代表 a任务付出了 j 时间 ,$f[i][j] $ 表示第i个任务 b 任务用到的最短时间 。
$ f[i,j] = 0$
if j < M a x A j<MaxA j<MaxA f [ i ] [ j ] = f [ i − 1 ] [ j ] + b [ i ] f[i][j]=f[i-1][j]+b[i] f[i][j]=f[i−1][j]+b[i]
f [ i , j ] = m i n ( f [ i − 1 , j − a [ i ] ] + b [ i ] , f [ i − 1 , j ] ) f[i,j] = min(f[i-1,j-a[i]]+b[i],f[i-1,j]) f[i,j]=min(f[i−1,j−a[i]]+b[i],f[i−1,j]) b 的 、、a的
初始化的问题 :一定要注意!!!
#include <bits/stdc++.h>
#define Max INT_MAX
using namespace std ;
const int N = 1e4+10 ;
int f[N][N] ;
int a[N] ;
int b[N] ;
int timer[N] ;
int n ;
int dp(){
memset(f , 0 , sizeof f) ;
memset(timer , 0x3f , sizeof timer) ;
int MaxA = 0;
for(int i = 1 ;i<=n ; i++){
MaxA += a[i] ;
for(int j = 0 ;j<=MaxA ;j++){
if(j<a[i])
f[i][j] = f[i-1][j] + b[i] ;
else
f[i][j] = min(f[i-1][j-a[i]],f[i-1][j]+b[i]) ;
timer[i] = min(timer[i],max(j , f[i][j])) ;
}
}
return timer[n] ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n) {
for(int i = 1; i <= n; i++) {
ifs >> a[i];
}
for(int i = 1; i <= n; i++) {
ifs >> b[i];
}
ifs.close();
} else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int sum, const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << sum <<endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main(){
string baseFolder = "F:\\桌面\\算法设计与分析\\第3章动态规划实验\\prog31独立任务最优调度问题\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\sched"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\sched"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\sched"; // 正确答案文件夹路径
for (int i = 0; i <= 10; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
// cout << s << " " << testFilePath << endl;
read(testFilePath);
int res = dp() ;
string answerFilePath = answerFolder + s + ".txt";
write(res ,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0 ;
}
二、石子合并问题(圆形)
难点 如何处理首位可以相连的问题!!
解决方法:开两倍长的数组最后区每段的最大最小值
找最大值和最小值
s u m [ N ] sum[N] sum[N] 是前缀和
找状态方程:
$dpmin[i][j]=min(dpmin[i][j],dpmin[i][k]+dpmin[k+1][j]+sum[j]-sum[i-1]) $
$dpmax[i][j]=min(dpmax[i][j],dpmax[i][k]+dpmax[k+1][j]+sum[j]-sum[i-1]) $
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4+10 ;
int dpmin[N][N] ;
int dpmax[N][N] ;
int sum[N] ;
int n ;
int a[N] ;
int maxx , minn ;
void dp(){
memset(sum, 0 , sizeof sum) ;
memset(dpmin , 0x3f ,sizeof dpmin) ;
memset(dpmax, 0 , sizeof dpmax) ;
for(int i =1 ; i<=2*n ; i++){
sum[i] =sum[i-1]+a[i] ;
dpmin[i][i] = 0 ,dpmax[i][i] = 0 ;
}
for(int len=1 ; len<=2*n ;len++ ){
for(int i=1; i+len<=2*n ; i++){
int j = i+len ;
for(int k = i; k <j ;k++ ){
dpmin[i][j] = min(dpmin[i][k]+dpmin[k+1][j]+sum[j]-sum[i-1],dpmin[i][j]) ;
}
}
}
for(int len =1; len <=2*n ;len++){
for(int i=1; i+len<= 2*n ; i++){
int j =i +len ;
for(int k = i; k < j ;k++ ){
dpmax[i][j] = max(dpmax[i][k]+dpmax[k+1][j]+sum[j]-sum[i-1],dpmax[i][j]) ;
}
}
}
minn = INT_MAX ;
maxx = 0 ;
for(int i=1;i<=n;i++)
{
minn=min(minn,dpmin[i][i+n-1]); //Min[1,n],f[2,n+1]..f[n,2n-1]
maxx=max(maxx,dpmax[i][i+n-1]); //Max[1,n],g[2,n+1]..g[n,2n-1]
}
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n) {
for(int i = 1; i <= n; i++) {
ifs >> a[i];
a[i+n] = a[i] ;
}
ifs.close();
} else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int sum,int k ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << sum <<endl ;
ofs << k <<endl;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{ string baseFolder = "F:\\桌面\\算法设计与分析\\第3章动态规划实验\\prog33石子合并问题\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\merge"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\merge"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\merge"; // 正确答案文件夹路径
for (int i = 0; i <= 9; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
dp() ;
string answerFilePath = answerFolder + s + ".txt";
write(minn,maxx,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
三、 最小 m 段和问题
问题是区间划分和的最大值所有情况中的最小值
d p [ i ] [ j ] dp[i][j] dp[i][j] i表示i个数 ,j表示划分j块 。
s u m [ N ] sum[N] sum[N] 是前缀和
d p [ i ] [ j ] = m i n ( d p [ i ] [ j ] , m a x ( d p [ k ] [ j − 1 ] , s u m [ i ] − s u m [ k ] ) dp[i][j] = min(dp[i][j],max(dp[k][j-1],sum[i]-sum[k]) dp[i][j]=min(dp[i][j],max(dp[k][j−1],sum[i]−sum[k]) ; k表示划分到第几个
d p [ 0 ] [ 0 ] = 0 dp[0][0] = 0 dp[0][0]=0 有个测试点会给到!!
#include <bits/stdc++.h>
using namespace std;
const int N = 110 ;
int n ,m ;
int a[N] ;
int dp[N][N] ;
int sum[N] ;
int dpp(){
memset(dp , 0x3f , sizeof dp) ;
dp[0][0] = 0 ;
for(int i = 1 ;i<=n ;i++){
dp[i][1] = sum[i] ;
for(int j = 2 ; j<=min(m,i) ; j++){
for(int k = 2 ;k<i ; k++){
dp[i][j] = min(dp[i][j] ,max(dp[k][j-1],sum[i]-sum[k])) ;
}
}
}
return dp[n][m] ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n) {
sum[0] = 0 ;
ifs >> m ;
for(int i = 1; i <= n; i++) {
ifs >> a[i];
sum[i] = sum[i-1] + a[i] ;
}
ifs.close();
} else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int sum ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << sum <<endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{ string baseFolder = "F:\\桌面\\算法设计与分析\\第3章动态规划实验\\prog38最小m段和问题\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\sum"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\sum"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\sum"; // 正确答案文件夹路径
for (int i = 0; i <= 9; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
int res = dpp() ;
string answerFilePath = answerFolder + s + ".txt";
write(res,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
四、最大k乘积问题
d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , d p [ k ] [ j − 1 ] ∗ ( n u m [ i ] m o d w g ( i − k ) ) ) dp[i][j] = max(dp[i][j],dp[k][j-1]*(num[i] mod wg(i-k))) dp[i][j]=max(dp[i][j],dp[k][j−1]∗(num[i]modwg(i−k)))
注意 :处理数的储存 。
#include <bits/stdc++.h>
using namespace std;
const int N = 11 ;
int dp[N][N] ;
int n , m,sum ;
int num[N] ;
int wg(int s){
int k = 1 ;
while(s--) k*=10 ;
return k ;
}
int dpp(){
memset(dp , -1 ,sizeof dp) ;
dp[0][0] = 0 ;
for(int i = 1 ;i<= n ;i++ ){
dp[i][1] = num[i] ;
for(int j =2 ;j<=min(m,i) ;j++){
for(int k = 2 ;k<i ; k++){
dp[i][j] = max(dp[i][j],dp[k][j-1]*(num[i]%wg(i-k)));
}
}
}
return dp[n][m] ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n) {
ifs >> m ;
ifs >> sum ;
num[n] = sum ;
for(int i = n-1 ; i>=1 ;i--){
num[i] = num[i+1]/10;
}
ifs.close();
} else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int sum ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << sum << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{ string baseFolder = "F:\\桌面\\算法设计与分析\\第3章动态规划实验\\prog313最大k乘积问题\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\kmul"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\kmul"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\kmul"; // 正确答案文件夹路径
for (int i = 0; i <= 9; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
int res = dpp() ;
string answerFilePath = answerFolder + s + ".txt";
write(res,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
第四章、 贪心算法
一、会场安排
没有用到贪心 直接用 b [ N ] b[N] b[N] 数组记录在下标 i 时刻有几个任务
最后遍历数组看最大的即是会场需要最少的安排。
#include <bits/stdc++.h>
using namespace std;
const int N =1e8+10 ;
int n ;
int b[N] ;
int main()
{
cin >> n ;
while(n--){
int a , c ;
cin >> a >> c ;
b[a] += 1 ;
b[c] -=1 ;
}
int res = 0 ;
for(int i=0 ;i<N ;i++) b[i] = b[i-1] + b[i] ;
for(int i=0 ;i<N ;i++) res = max(b[i] , res ) ;
cout << res ;
return 0;
}
贪心策略:
if(w[j]<b[i].start) w[j] = b[i].endd ;//此时的i进入到与j同一个会场
利用 w [ N ] w[N] w[N] 数组记录 w [ j ] w[j] w[j] 第j 个所在的会场最晚的时间 ;
因为已经按最早的时间排序 ,所以不会出现漏排的情况 ;
如果 j > s u m j>sum j>sum 说明需要新加一个会场 ;
#include <bits/stdc++.h>
using namespace std;
const int N =1e5 +10 ;
int n ,sum;
struct Meeting {
int start;
int endd;
};
Meeting b[N];
int w[N] ;//活动会场末时间
bool com( Meeting a, Meeting b ){
//if(a.a==b.c) return a.c <b.c ;
return a.start < b.start ;
}
int tx() {
for(int i= 1 ;i<=n ;i++){
w[i] = 0 ;
}
for(int i = 1 ;i<=n ;i++){
for(int j=1 ;j <=n ;j++){
if(w[j] <=b[i].start){
w[j] = b[i].endd ;
if(j>sum ) sum++ ;
break ;
}
}
}
return sum ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n) {
for(int i=1 ;i<=n ;i++){
ifs >> b[i].start ;
ifs >> b[i].endd ;
}
ifs.close();
} else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int sum ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << sum << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{
string baseFolder = "F:\\桌面\\算法设计与分析\\第4章贪心算法实验测试数据\\prog41会场安排\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\sche"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\sche"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\sche"; // 正确答案文件夹路径
for (int i = 0; i <= 12; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
sort(b+1,b+n+1 ,com) ;
memset(w , 0 ,sizeof w ) ;
sum =0 ;
int res = tx() ;
string answerFilePath = answerFolder + s + ".txt";
write(res,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
二、 最优合并问题
p r i o r i t y q u e u e < i n t , v e c t o r < i n t > , g r e a t e r < i n t > > q m a x ; priority _ queue<int , vector<int> ,greater<int> > qmax ; priorityqueue<int,vector<int>,greater<int>>qmax; 小根堆 ;
p r i o r i t y q u e u e < i n t , v e c t o r < i n t > , l e s s < i n t > > q m i n ; priority_queue<int , vector<int> , less<int> > qmin ; priorityqueue<int,vector<int>,less<int>>qmin; 大根堆 ;
每执行完一个文件后要恢复原来的值 ;
#include <bits/stdc++.h>
using namespace std;
priority_queue<int , vector<int> ,greater<int> > qmax ;
priority_queue<int , vector<int> , less<int> > qmin ;
int hh ,tt , n ;
void mmax(){
while(qmax.size()>1){
int t ,t1 ;
t = qmax.top();
qmax.pop() ;
t1 = qmax.top() ;
qmax.pop() ;
qmax.push(t1+t) ;
tt += t1+t-1;
}
while(qmax.size())qmax.pop() ;
}
void mmin(){
while(qmin.size()>1){
int t ,t1 ;
t = qmin.top();
qmin.pop() ;
t1 = qmin.top() ;
qmin.pop() ;
qmin.push(t1+t) ;
hh += t1+t-1;
}
while(qmin.size())qmin.pop() ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n) {
for(int i=1 ;i<=n ;i++){
int t ;
ifs >> t ;
qmax.push(t) ;
qmin.push(t) ;
}
ifs.close();
} else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int sum ,int res ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << sum <<" " <<res << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{
string baseFolder = "F:\\桌面\\算法设计与分析\\第4章贪心算法实验测试数据\\prog42最优合并\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\merge"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\merge"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\merge"; // 正确答案文件夹路径
for (int i = 0; i <= 10; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
tt=0;
hh=0;
mmax() ;
mmin() ;
string answerFilePath = answerFolder + s + ".txt";
write(hh,tt,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
三、程序储存
比较简单没啥可写的
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10 ;
int n ,sum , res ;
int a[N] ;
bool com(int c ,int b){
return c<b ;
}
void tx(){
int i = 0;
while(sum){
sum -= a[i] ;
i++;
if(sum>=0) res++ ;
if(i==n) break ;
}
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n) {
ifs >> sum ;
for(int i=0 ;i<n ;i++){
ifs >>a[i] ;
}
ifs.close();
} else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int sum ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << sum << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{
string baseFolder = "F:\\桌面\\算法设计与分析\\第4章贪心算法实验测试数据\\prog45程序存储\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\prog"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\prog"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\prog"; // 正确答案文件夹路径
for (int i = 0; i <= 10; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
memset(a, 0 ,sizeof a) ;
read(testFilePath);
sort(a ,a+n , com) ;
res = 0;
tx() ;
string answerFilePath = answerFolder + s + ".txt";
write(res,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
四、最优服务次序问题
也比较简单;
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10 ;
int n ;
double res ;
int a[N] ;
bool com(int c ,int b){
return c<b ;
}
void tx(){
for(int i=1 ;i<n ;i++){
a[i]= a[i-1]+a[i] ;
}
for(int i = 0 ;i< n ;i++) res +=a[i] ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n) {
for(int i=0 ;i<n ;i++){
ifs >>a[i] ;
}
ifs.close();
} else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(double sum ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << fixed <<setprecision(2) << sum << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{
string baseFolder = "F:\\桌面\\算法设计与分析\\第4章贪心算法实验测试数据\\prog46最优服务次序\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\wait"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\wait"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\wait"; // 正确答案文件夹路径
for (int i = 0; i <= 9; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".IN";
memset(a, 0 ,sizeof a) ;
read(testFilePath);
sort(a ,a+n , com) ;
res = 0;
tx() ;
res = res /n ;
string answerFilePath = answerFolder + s + ".txt";
write(res,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
五、汽车加油
#include <bits/stdc++.h>
using namespace std;
const int N =1e5+10 ;
int n , k ;
int a[N] ;
bool fl ;
int wg(){
int s = n ;
int res = 0 ;
fl = true ;
for(int i = 0 ;i<k ;i++){
s -= a[i] ;
if (s<0) fl = false ;
if(s<a[i+1]){
s = n ;
res++ ;
}
}
return res ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n) {
ifs >> k ;
for(int i=0 ;i<=k ;i++){
ifs >>a[i] ;
}
ifs.close();
} else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int sum ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
if(fl)
ofs << sum << endl ;
else
ofs << "No Solution!" <<endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{
string baseFolder = "F:\\桌面\\算法设计与分析\\第4章贪心算法实验测试数据\\prog49汽车加油\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\oil"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\oil"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\oil"; // 正确答案文件夹路径
for (int i = 0; i <= 10; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
int res = wg() ;
string answerFilePath = answerFolder + s + ".txt";
write(res,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
六、最优分解问题
#include <bits/stdc++.h>
using namespace std;
const int N= 1e5+10 ;
int n ;
int a[N] ;
vector<int > wg ;
vector<int> mul(vector<int> &A,int b)
{
int t=0; //进位
vector<int> C;
for(int i=0; i<A.size() || t ;i++)
{
if(i<A.size()) t += A[i]*b;
C.push_back(t%10);
t/=10;
}
return C;
}
vector<int > txt(){
vector<int > c ;
if(n==1||n==2){
c.push_back(1) ;
return c ;
}
if(n==3){
c.push_back(2) ;
return c ;
}
if(n==4){
c.push_back(3) ;
return c ;
}
int k = 1 ;
int s = n ;
int res = 1;
a[0] = 2 ;
s-=2 ;
while(s){
if(s>a[k-1]){
a[k]= a[k-1]+1 ;
s-=a[k] ;
k++ ;
}
else{
int f = s/k ;
int g = s%k ;
for(int i=0 ;i<k ;i++) a[i]+=f ;
for(int i=k-1 ;i>=k-g;i--) a[i]++ ;
s=0 ;
}
}
c.push_back(1) ;
for(int i=0 ;i<k ;i++){
c = mul(c,a[i]) ;
// cout << a[i] << endl ;
int p = c.size() ;
// for(int j=p-1 ;j>=0 ;j--) cout << c[j] ;
// cout << endl ;
}
return c ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n){
ifs.close();
}
else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(vector<int> &A ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
int k = A.size() ;
for(int i=k-1 ;i>=0 ;i--) ofs << A[i] ;
ofs << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{ string baseFolder = "F:\\桌面\\算法设计与分析\\第4章贪心算法实验测试数据\\prog415最优分解\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\maxm"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\maxm"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\maxm"; // 正确答案文件夹路径
for (int i = 0; i <= 10; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
wg = txt() ;
string answerFilePath = answerFolder + s + ".txt";
write(wg,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
第五章、 回溯法
一、 子集和问题
s t [ N ] st[N] st[N] 是判断是否选择 , 这里有两个剪枝
t w tw tw 是当前的和 , r w rw rw 是剩余和 ;
#include <bits/stdc++.h>
using namespace std;
const int N = 10010 ;
int a[N] ;
int n ,c ;
int tw ,rw ;
bool st[N] ;
bool flag ;
string answerFilePath ;
void write(string cc ,const string& file);
void backtrack(int x){
if(flag==true) return ;
if(x>n){
if(tw==c){
string cc ="" ;
for(int i=1;i<=x ;i++){
if(st[i]==true) {
cc += to_string(a[i]) ;
cc +=" " ;
}
}
// cout << cc <<endl ;
write(cc,answerFilePath);
flag = true ;
return ;
}
return ;
}
if(tw+a[x]<=c){
st[x] = true ;
rw -=a[x] ;
tw+= a[x] ;
backtrack(x+1) ;
rw += a[x];
tw -= a[x] ;
}
if(tw+rw-a[x] >=c){
st[x] = false ;
rw -= a[x] ;
backtrack(x+1) ;
rw += a[x] ;
}
return ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n){
ifs >>c ;
for(int i = 1 ;i<=n ;i++) {
ifs >>a[i] ;
rw += a[i] ;
}
ifs.close();
}
else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(string cc ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << cc ;
// cout << "写入成功" <<endl ;
ofs << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{ string baseFolder = "F:\\桌面\\算法设计与分析\\第五章回溯法实验\\prog51子集和问题\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\subsum"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\subsum"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\subsum"; // 正确答案文件夹路径
for (int i = 0; i <= 10; i++) {
tw = 0 , rw = 0 ;
flag = false ;
memset(st ,0,sizeof st) ;
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
answerFilePath = answerFolder + s + ".txt";
backtrack( 1 ) ;
string wg ;
if(flag==false)
{wg ="No Solution!" ;
write(wg,answerFilePath);}
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
二、 最小重量机器设计
int n ,m ,d ;
int w[N][N] , v[N][N] ;
int minw ;//最小重量
int st[N] ; //暂存
int p[N] ;//储存最后的方案
函数中注意 :
$ backtrack(x+1 , wt+w[x][i] , c+v[x][i]) ;$ 不能直接修改wt 和 c 的值 不然回溯会错 ,或者修改后得复原 ,不然直接在上面写
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10 ;
int n ,m ,d ;
int w[N][N] , v[N][N] ;
int minw ;//最小重量
int st[N] ; //暂存
int p[N] ;//储存最后的方案
void backtrack(int x , int wt ,int c){
if(x>n){
if(wt<minw){
minw = wt ;
for(int i = 1 ;i<=n ;i++){
p[i] = st[i] ;
}
}
return ;
}
for(int i = 1 ; i<=m ;i++){
if(w[x][i]+wt<minw && v[x][i]+c <=d){
st[x] = i ;
backtrack(x+1 , wt+w[x][i] , c+v[x][i]) ;
st[x] = 0 ;
}
}
return ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n){
ifs >>m >> d ;
for(int i = 1 ; i<=n ;i++){
for(int j = 1 ;j<=m ; j++){
ifs >> v[i][j] ;
}
}
for(int i = 1 ; i<=n ;i++){
for(int j = 1 ;j<=m ; j++){
ifs >> w[i][j] ;
}
}
ifs.close();
}
else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int wg ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << wg << endl ;
for(int i =1 ; i<=n ;i++){
ofs <<p[i] << " " ;
}
// cout << "写入成功" <<endl ;
ofs << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{ string baseFolder = "F:\\桌面\\算法设计与分析\\第五章回溯法实验\\prog53最小重量机器设计\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\machine"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\machine"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\machine"; // 正确答案文件夹路径
for (int i = 0; i <= 10; i++) {
minw = 0x3f3f3f3f ;
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
string answerFilePath = answerFolder + s + ".txt";
backtrack( 1,0 ,0 ) ;
int wg = minw ;
write(wg,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
三、 无和集
判断函数
$f[i][f[i][0]+1] = x $ 判断是否可行 ;可行的话 f [ i ] [ 0 ] + + f[i][0]++ f[i][0]++ 进行 d f s ( x + + ) dfs(x++) dfs(x++)
#include <bits/stdc++.h>
using namespace std;
const int N= 1e4+10 ;
int n ;
int num ;
int f[N][N] , res[N][N] ;
int judge(int t,int k){
for(int i=1;i<=f[k][0];i++){
for(int j=i+1;j<=f[k][0];j++){
if(f[k][i]+f[k][j]==t)
return 0;
}
}
return 1;
}
void dfs(int x){
if(x > num){
for(int i = 1 ;i<=n ;i++){
for(int j = 0 ;j<=f[i][0] ;j++){
res[i][j] = f[i][j] ;
}
}
num = x ;
}
for(int i=1; i<=n ;i++){
f[i][f[i][0]+1] = x ;
if(judge(x,i)){
f[i][0]++ ;
dfs(x+1) ;
f[i][0]-- ;
}
}
return ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n){
cout <<n <<endl ;
ifs.close();
}
else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int wg ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << wg << endl ;
ofs << endl ;
for(int i =1 ;i<=n ;i++){
for(int j = 1 ;j<=res[i][0];j++){
ofs << res[i][j] << " " ;
}
ofs << endl ;
ofs << endl ;
}
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{ string baseFolder = "F:\\桌面\\算法设计与分析\\第五章回溯法实验\\prog56无和集\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\nosum"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\nosum"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\nosum"; // 正确答案文件夹路径
for (int i = 2; i <= 9; i++) {
num =0 ;
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
string answerFilePath = answerFolder + s + ".txt";
dfs(1) ;
int wg = num-1 ;
write(wg,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
四、 工作分配问题
#include <bits/stdc++.h>
using namespace std;
const int N= 22;
int n ;
int a[N][N] ;
int c ,cmin ;
bool st[N] ;
void backtrack(int x ){
// cout <<x << endl ;
if(x>n){
// cout << c << " - > " <<cmin
if(cmin>c){
cmin = c ;
}
return ;
}
for(int i = 1 ;i<=n ; i++){
if(st[i]) continue ;
else{
st[i] = true ;
c+=a[x][i] ;
backtrack(x+1) ;
st[i] = false ;
c-=a[x][i] ;
}
}
return ;
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n){
for(int i = 1 ;i<=n ;i++){
for(int j =1 ; j<=n ;j++){
ifs >> a[i][j] ;
}
}
ifs.close();
}
else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int wg ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << wg << endl ;
// cout << "写入成功" <<endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{ string baseFolder = "F:\\桌面\\算法设计与分析\\第五章回溯法实验\\prog513工作分配\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\job"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\job"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\job"; // 正确答案文件夹路径
for (int i = 0; i <= 9; i++) {
cmin = 0x3f3f3f3f ;
c = 0 ;
memset(st , 0 ,sizeof st) ;
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
string answerFilePath = answerFolder + s + ".txt";
backtrack( 1 ) ;
int wg = cmin ;
write(wg,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
五、 最优调度
#include <bits/stdc++.h>
using namespace std;
const int N = 21 ;
int n , k ;
int t[N] ;
int a[N] ;
int c ,cmin ;
void dfs(int x ){
if(x>n){
c = 0 ;
for(int i = 1 ;i<=k ; i++){
c = max(t[i] , c) ;
}
if(c < cmin) cmin = c ;
return ;
}
for(int i = 1 ; i<=k ; i++){
t[i] += a[x] ;
dfs(x+1) ;
t[i] -= a[x] ;
}
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n){
ifs >> k ;
for(int i = 1 ;i<=n ;i++){
ifs >> a[i] ;
}
ifs.close();
}
else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int wg ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << wg << endl ;
// cout << "写入成功" <<endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{
string baseFolder = "F:\\桌面\\算法设计与分析\\第五章回溯法实验\\prog515最佳调度\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\machine"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\machine"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\machine"; // 正确答案文件夹路径
for (int i = 0; i <= 10; i++) {
cmin = 0x3f3f3f3f ;
memset(t , 0 ,sizeof t) ;
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
string answerFilePath = answerFolder + s + ".txt";
dfs(1) ;
int wg = cmin ;
write(wg,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
第六章、 分支定界
一、最小机器重量设计
如何定义优先级
通过struct重载()操作符,定义了一个函数对象
struct cmp{
bool operator()(vector<int>&a,vector<int>&b){
return a[0]>b[0];
}
};
priority_queue<vector<int>,vector<vector<int>>,cmp> q;//小顶堆
可以使用函数指针作为第三个模板参数,指定比较函数。
例如,如果要按照元素值从大到小排序(小顶堆),则可以这样定义:
struct MyType {
int val;
};
bool cmp(const MyType& a, const MyType& b) {
return a.val > b.val; // 从小到大排序
}
priority_queue<MyType, vector<MyType>, decltype(&cmp)> pq(&cmp);
重写’<'操作符:
struct node
{
int x, y;
node(int x,int y):x(x),y(y){}
};
bool operator< (node a,node b)
{
if(a.x == b.x) return a.y >= b.y;
else return a.x > b.x;
}
priority_queue<node> pq; //只传node,但是node结构体的<运算符已被改变
#include<bits/stdc++.h>
using namespace std;
const int N = 22 ;
int n; //部件数量
int m; //供应商数量
int d; //价格上限
int bestw; //最小的重量
int c[N][N] ; //二维数组,每个部件不同商家的价格
int w[N][N] ;//二维数组,每个部件不同商家的重量
int result[N] ;//结果 ;
//每一个部件的信息
class Node
{
public:
int weight; //当前已选机器的重量和
int val; //当前已选机器的价值和
int source; //哪个供货商
int level; //第几层,也代表了第几个部件
int priority; //优先级
Node *father;
};
Node *leaf;//叶子结点
//优化的优先级设定
bool operator<(Node a,Node b) //level按照减序
{
if(a.priority == b.priority)return a.level < b.level; //如果重量相同,选择level大的。
else if(a.level==b.level) return a.source > b.source ;
return a.priority > b.priority;//否则,重量小的先出队
}
//计算当前节点的优先级
void QueuePriority(Node a)
{
int currentMinW;
a.priority =a.weight;
//int temp_min_c = INT_MAX;
for(int i=a.level+1 ; i<=n ; i++)//选出剩余的部件在售货商中购买的最小质量,就是选择每一层最小的质量
{
currentMinW= INT_MAX;
for(int j=1;j<=m;j++) //每一层找最小的
{
currentMinW = currentMinW<w[i][j]?currentMinW:w[i][j];//从m个商家中选择当层重量最小的
}
a.priority+=currentMinW;
}
}
//约束函数
bool constraint(Node* pNode,int i){
if(pNode->val+c[pNode->level +1][i] <=d && pNode->weight +w[pNode->level +1][i] <= bestw){
return true;
}
return false;
}
//创建节点
Node createNode(int level,Node* father,int source,int val,int weight){
Node newNode;
newNode.level = level;//层次加1
newNode.father = father;
newNode.source = source;
newNode.val =val ;
newNode.weight = weight;
return newNode;
}
void MinWeightMachine()
{
bestw = INT_MAX;
Node initial;
initial=createNode(0,NULL,0,0,0);
QueuePriority(initial); //计算优先级
priority_queue<Node> heap; //用优先队列,建立一个最小堆。加入进去就会自动排好序的。
heap.push(initial);
while(!heap.empty())
{
Node *pNode = new Node(heap.top());
heap.pop();//队首元素作为父节点出队,即优先级值小的活结点先扩展
if(pNode->level == n)//到达叶节点,不能扩展 ,得到一个解
{
if(pNode->weight <bestw) //更新
{
bestw = pNode -> weight;
//MinValue = pNode ->val;
leaf = pNode; //记录是最后是哪个结点数据,便于回溯找最优解
}
}
else
{
for(int i=1;i<=m;i++)//扩展结点,依次选择每个售货商,每次都是m叉树
{
//可行性剪枝和限界剪枝
if(constraint(pNode,i))
{
Node newNode;//生儿子结点
newNode=createNode(pNode->level +1,pNode,i,pNode->val + c[pNode->level +1][i],pNode->weight + w[pNode->level +1][i]);
QueuePriority(newNode); //计算优先值
heap.push(newNode);//儿子入队
}
}
}
}
for(int i=n;i>=1;i--)
{
result[i] = leaf ->source;//从最后叶子结点回溯到根节点
leaf = leaf ->father;
}
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n){
ifs >>m >> d ;
for(int i = 1 ; i<=n ;i++){
for(int j = 1 ;j<=m ; j++){
ifs >> c[i][j] ;
}
}
for(int i = 1 ; i<=n ;i++){
for(int j = 1 ;j<=m ; j++){
ifs >> w[i][j] ;
}
}
ifs.close();
}
else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int wg ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
ofs << wg << endl ;
for(int i =1 ; i<=n ;i++){
ofs <<result[i] << " " ;
}
// cout << "写入成功" <<endl ;
ofs << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{
string baseFolder = "F:\\桌面\\算法设计与分析\\第六章分支限界法\\prog64最小重量机器设计\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\machine"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\machine"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\machine"; // 正确答案文件夹路径
for (int i = 0; i <= 6; i++) {
leaf = NULL;
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
string answerFilePath = answerFolder + s + ".txt";
MinWeightMachine();
int wg = bestw ;
write(wg,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
}
二、n皇后问题
分支定界是宽搜,记得节点的
int dg[2*N][2*N] , udg[2*N][2*N] , c[N] , l[N] ;
#include <bits/stdc++.h>
using namespace std;
const int N = 12;
int res[N] ;
int n ;
struct node{
int ce ;
int le ;
int ans[N] ;
bool dg[2*N] , udg[2*N] , c[N] , l[N] ;
};
void bfs() {
queue<node> q;
bool found = false; // 添加标志来标记是否已经找到一个解
for (int i = 1; i <= n; i++) {
node k;
memset(k.dg, 0, sizeof k.dg);
memset(k.udg, 0, sizeof k.udg);
memset(k.c, 0, sizeof k.c);
memset(k.l, 0, sizeof k.l);
k.ce = 1;
k.le = i;
k.ans[k.ce] = k.le;
q.push(k);
}
while (!q.empty() && !found) {
node t = q.front();
q.pop();
if (!t.c[t.ce] && !t.l[t.le] && !t.dg[t.ce + t.le] && !t.udg[n - t.ce + t.le]) {
t.c[t.ce] = true;
t.l[t.le] = true;
t.dg[t.ce + t.le] = true;
t.udg[n - t.ce + t.le] = true;
t.ans[t.ce] = t.le;
if (t.ce == n) {
for (int i = 1; i <= n; i++) res[i] = t.ans[i]; // 更新res数组
found = true; // 标记已经找到一个解
break;
}
for (int i = 1; i <= n; i++) {
int x = t.ce + 1;
node neww;
neww.ce = x;
neww.le = i;
for (int j = 1; j <= 2 * n; j++) {
neww.dg[j] = t.dg[j];
neww.udg[j] = t.udg[j];
}
for (int j = 1; j <= n; j++) {
neww.c[j] = t.c[j];
neww.l[j] = t.l[j];
}
if (!neww.c[x] && !neww.l[i] && !neww.dg[x + i] && !neww.udg[n - x + i]) {
for (int j = 1; j <= n; j++) neww.ans[j] = t.ans[j];
neww.ans[x] = i; // 更新当前节点的解
q.push(neww);
}
}
}
}
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n){
ifs.close();
}
else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
for(int i =1 ; i<=n ;i++){
ofs <<res[i] << " " ;
}
// cout << "写入成功" <<endl ;
ofs << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{ string baseFolder = "F:\\桌面\\算法设计与分析\\第六章分支限界法\\prog66n皇后问题\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\queen"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\queen"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\queen"; // 正确答案文件夹路径
for (int i = 0; i <= 7; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
string answerFilePath = answerFolder + s + ".txt";
bfs() ;
write(answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
return 0;
}
三、最优调度问题
记得初始化!!!!!!!!!!!!!!
#include <bits/stdc++.h>
using namespace std;
const int N =22 ;
int n ,k ;
int a[N] ;
int best ;
struct node{
int time[N] ; // 第几个的时间
int lev ; // 第几层
int tt ; //最长的时间
bool operator <(const node&a)const{
return tt > a.tt ;
}
};
priority_queue<node> q ;
void bfs(){
best = 0x3f3f3f3f ;
for(int j = 1 ;j<=k ;j++){
node in ;
in.lev = 1 ;
for(int i = 1 ;i<=k ;i++) in.time[i] = 0 ;//这一步很关键!!
in.time[j] = a[1] ;
in.tt = a[1] ;
q.push(in) ;
}
while(q.size()){
node t = q.top() ;
q.pop() ;
if(t.lev==n){
best = min(best , t.tt) ;
}
else{
for(int i= 1 ;i<=k ;i++){
int x = t.lev+1 ;//层数 ;
node neww ;
neww.lev = x ;
neww.tt = max(t.tt , t.time[i]+a[x]) ;
if(neww.tt < best){
for(int j= 1 ;j<=k ;j++){
neww.time[j] = t.time[j] ;
}
neww.time[i] += a[x] ;
q.push(neww) ;
}
}
}
}
}
void read(const string& file) {
ifstream ifs(file.c_str(), ios::in);
if (ifs >> n){
ifs >>k ;
for(int i = 1 ;i<=n ; i++){
ifs >> a[i] ;
}
ifs.close();
}
else {
cerr << "读取文件错误:" << file << endl;
return ;
}
}
void write(int wg ,const string& file) {
ofstream ofs;
ofs.open(file.c_str(), ios::out);
// cout << "写入成功" <<endl ;
ofs <<wg << endl ;
ofs.close() ;
}
void comparejugle(const string& fileA, const string& fileB) {
ifstream ifsA(fileA.c_str()), ifsB(fileB.c_str());
string contentA((istreambuf_iterator<char>(ifsA)), istreambuf_iterator<char>());
string contentB((istreambuf_iterator<char>(ifsB)), istreambuf_iterator<char>());
if (contentA != contentB) {
cout << "不一致" << endl;
cout <<contentA << endl ;
cout << contentB << endl ;
} else {
cout << "一致" << endl;
}
}
int main()
{ string baseFolder = "F:\\桌面\\算法设计与分析\\第六章分支限界法\\prog68最佳调度问题\\"; // 基础文件夹路径
string testFolder = baseFolder + "test\\machine"; // 测试文件夹路径
string answerFolder = baseFolder + "myanswer\\machine"; // 答案文件夹路径
string correctAnswerFolder = baseFolder + "answer\\machine"; // 正确答案文件夹路径
for (int i = 0; i <= 10; i++) {
stringstream ss;
ss << i;
string s = ss.str();
string testFilePath = testFolder + s + ".in";
read(testFilePath);
string answerFilePath = answerFolder + s + ".txt";
bfs() ;
int wg = best ;
write(wg ,answerFilePath);
string correctAnswerFilePath = correctAnswerFolder + s + ".out";
comparejugle(answerFilePath, correctAnswerFilePath);
}
cout << best ;
return 0;
}