当前位置: 首页 > news >正文

GXUOJ-算法-第四次作业(圆排列、连续邮资、n皇后、符号三角形)

1.圆排列

问题描述

GXUOJ | 圆排列

代码解答

#include<bits/stdc++.h>
using namespace std;
int n;
int r[1000];//存放半径double calculate(int r[],int n,double minL){double x,y;//表示两个圆的半径double sum=0;for(int i=1;i<n;i++){//取大的半径为x,小的为yif(r[i]>r[i+1]){x=r[i];y=r[i+1];}else{y=r[i];x=r[i+1];}//两个圆的矩形边方向的距离sum+= sqrt((x+y)*(x+y)-(x-y)*(x-y));if(sum>minL)//可以剪枝优化一下,如果当前sum已经大于minL直接结束当前循环break;}sum+=r[1]+r[n];//加上开头和结束minL=min(minL,sum);return minL;
}int main(){cin>>n;double ans=DBL_MAX;//取一个无穷大for(int i=1;i<=n;i++){cin>>r[i];}do{ans=calculate(r,n,ans);}while(next_permutation(r+1,r+n+1));//全排列printf("%.2f",ans-0.005);//减去0.005来进行浮点数精度修正
}

但是这个算法考虑的全是圆相切的情况,并没有考虑如下的情况

圆排列问题详解(原理+代码)_对n个圆的最优排列问题,深度优先遍历其排列树所需要的辅助空间-CSDN博客

 代码更改

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f; 
int n;
int r[1000];	// 定义数组 r,用于存储每个圆的半径
double x[1000];	// 定义数组 x,计算每个圆的中心位置
double ans = INF;
// 计算当前圆排列下的覆盖区间长度
double calculate() {memset(x, 0, sizeof x);// 将数组 x 全部初始化为 0,用于重新计算每个圆的中心位置for (int i = 0; i < n; i++) {for (int j = 0; j < i; j++)// 对于每个圆 i,计算它与之前所有圆 j 的位置关系,以确定其中心位置x[i] = max(x[i], x[j] + sqrt(4 * r[i] * r[j]));}double low = INF, high = -INF;// 初始化 low 为一个较大的值,high 为一个较小的值,用于记录所有圆覆盖区间的最小和最大边界for (int i = 0; i < n; i++) {low = min(low, x[i] - r[i]);high = max(high, x[i] + r[i]);}return high - low;// 返回当前圆排列下的覆盖区间长度
}int main() {cin >> n;for (int i = 0; i < n; i++)cin >> r[i];do {ans = min(ans, calculate());// 计算当前圆的排列下的覆盖区间长度,并更新最小覆盖区间长度 ans} while (next_permutation(r, r + n));printf("%.2lf", floor(ans * 100) / 100);return 0;
}

2.连续邮资

问题描述

GXUOJ | 连续邮资

代码解答

#include<bits/stdc++.h>
using namespace std;
int n, m;//n为邮票种类,m为一封信上最多贴的邮票个数
int Max;
int ans[10000];//最终答案数组//能否用n种邮票,面值在x数组中,最多贴m张,表示出sum(是个动态规划问题,
//方法是求出dp[n][sum]看它是否小于sum,状态转移方程
//dp[i][j]=min(dp[i-1][j-k*x[i]]+k)(其中dp[i][j]表示用到第i种邮票,
//表示邮资为j的最少邮票
bool panduan(int x[], int n, int sum){//dp[i][j]来表示使用前i种邮票凑出邮资j所需的最少邮票数int dp[15][1005]={0};for (int i = 1; i <= sum; i++)dp[1][i] = i;for (int i = 2; i <= n; i++){for (int j = 1; j <= sum; j++){dp[i][j] = 9999;for (int k = 0; k <= j / x[i]; k++)dp[i][j] = min(dp[i][j], dp[i - 1][j - x[i] * k] + k);}}if (dp[n][sum] > m)return false;return true;
}
void DFS(int x[], int cur, int max){if (cur == n){//如果已经得出了n种邮票if (max > Max){//并且它的最大值已经大于当前最大邮资数Max = max;for (int i = 1; i <= cur; i++)ans[i] = x[i];//更新答案数组}return;}for (int next = x[cur] + 1; next <= max + 1; next++)//如果还没得到n中邮票,那么从x[cur]+1~max+1选一个作为下一个邮资,因为max+1没法表示,所以必定到max+1为止{x[cur + 1] = next;//接下来是重点,用种类为cur+1,数目分别为x[1..cur+1]的邮票,最多使用m张,//能否表示出大于max的某个数int newMax=max;for (int i = max + 1; i <= m * x[cur + 1]; i++){//这个数最少要为max+1(不然没有意义了),最多是x[cur+1]*mif (panduan(x, cur + 1, i) == 0)//如果成立break;newMax=i;}if (newMax> max)//如果至少让最大值更新了一次DFS(x, cur + 1, newMax);}}
int main()
{cin >> n >> m;Max = 0;int x[1000]={0};//中间传递的数组,存储当前的邮票值的解x[1] = 1;DFS(x, 1, m);//x存储当前的解,cur表示当前传递到第几种邮票,max表示目前能表示到的最大值for (int i = 1; i <= n; i++)cout<<ans[i] <<" ";cout << endl;cout << Max;return 0;
}

3.n皇后问题

问题描述

GXUOJ | n皇后问题

代码解答

#include <bits/stdc++.h>
using namespace std;
const int N = 20;// bool数组用来判断搜索的下一个位置是否可行
// col列,dg对角线,udg反对角线
// g[N][N]用来存路径int n;
char g[N][N];
bool col[N], dg[N], udg[N];
int result = 0;void  dfs(int u) {// u == n 表示已经搜了n行,故输出这条路径if (u == n) {result++;return;}// 枚举u这一行,搜索合法的列int x = u;for (int y = 0; y < n; y++)// 剪枝(对于不满足要求的点,不再继续往下搜索)  if (col[y] == false && dg[y - x + n] == false && udg[y + x] == false) {col[y] = dg[y - x + n] = udg[y + x] = true;dfs(x + 1);col[y] = dg[y - x + n] = udg[y + x] = false;}
}int main() {cin >> n;dfs(0);cout << result;return 0;
}

无注释简化版

#include<bits/stdc++.h>
using namespace std;
const int N=20;
int n,result;
int col[N],dg[N],udg[N];
void dfs(int x){if(x==n){result++;return ;}for(int y=0;y<n;y++){if(col[y]==dg[y-x+n]==udg[x+y]==false){col[y]=dg[y-x+n]=udg[x+y]=true;dfs(x+1);col[y]=dg[y-x+n]=udg[x+y]=false;}}
}
int main(){cin>>n;dfs(0);cout<<result;
}

4.符号三角形

问题描述

GXUOJ | 符号三角形

代码解答

#include <bits/stdc++.h>
using namespace std;// n 表示符号三角形第一行的元素个数
//	cnt 用于积累符号三角形中1的元素个数 
int n, cnt = 0; 
// sum 用于统计满足条件的符号三角形的数量
int sum = 0; 
// p 数组用于存储符号三角形,p[i][j] 表示第 i 行第 j 列的元素
int p[25][25]; // 回溯函数,t 表示当前处理到符号三角形第一行的第 t 个位置
/*
剪枝条件:如果当前已经确定的 1 的数量超过了总数的二分之一,
或者剩余位置全为 1 时 1 的数量仍超过总数的二分之一,就返回
n*(n + 1)/4 是因为整个符号三角形元素总数为 n*(n + 1)/2 ,
1 的数量如果超过一半,就不可能满足 0 和 1 数量相等
t*(t - 1)/2 - cnt 表示假设剩余位置全为 1 时 1 的数量
前t行总元素为 t*(t+1)/2 ,减去 t和 cnt 假设剩余位置全为 1 时 1 的数量 
*/
void back(int t) {if (cnt > n * (n + 1) / 4 || t * (t - 1) / 2 - cnt > n * (n + 1) / 4) return; // 如果已经处理完符号三角形第一行的所有元素,说明成功构建了一个符号三角形 if (t > n) sum++; else{// 尝试在当前位置放置 0 或 1for (int i = 0; i < 2; i++) { // 在符号三角形第一行的第 t 个位置放置 ip[1][t] = i; // 更新当前已确定的 1 的数量cnt += i; // 根据上一行的元素确定当前行的元素for (int j = 2; j <= t; j++) { // 通过异或运算确定当前位置的元素,这里用异或模拟符号三角形的生成规则p[j][t - j + 1] = p[j - 1][t - j + 1] ^ p[j - 1][t - j + 2]; // 更新当前已确定的 1 的数量cnt += p[j][t - j + 1]; }// 递归处理下一个位置back(t + 1); // 回溯,恢复之前的状态,减去当前行已确定的 1 的数量for (int j = 2; j <= t; j++) { cnt -= p[j][t - j + 1]; }// 回溯,恢复之前的状态,减去当前位置放置的 1 的数量cnt -= i; }
}int main() {cin >> n; // 从符号三角形第一行的第一个位置开始回溯back(1); cout << sum; return 0;
}

没有注释版本

#include<bits/stdc++.h>
using namespace std;int n,sum,cnt;
int p[25][25];void back(int t){if(cnt>(n+1)*n/4|| t*(t-1)/2-cnt>(n+1)*n/4)	return;if(t>n) sum++;else{for(int i=0;i<2;i++){p[1][t]=i;cnt+=i;for(int j=2;j<=t;j++){p[j][t-j+1]=p[j-1][t-j+1]^p[j-1][t-j+2];cnt+=p[j][t-j+1]; }back(t+1);for(int j=2;j<=t;j++)cnt-=p[j][t-j+1];cnt-=i;}}
}
int main(){cin>>n;back(1);cout<<sum;return 0;
}


http://www.mrgr.cn/news/82176.html

相关文章:

  • Github拉取项目报错解决
  • 【车载网络】BUSOFF状态简述和制造
  • Spring实现输出带动态标签的日志
  • 【计算机网络】课程 作业一 搭建连续覆盖的办公网络
  • 多光谱图像的处理和分析方法有哪些?
  • WordPress新安装只安装主题后发现只有首页能打开,其他路由页面都是404,并且Elementor都打不开
  • 【非关系型数据库Redis 】 入门
  • primevue的<Menu>组件
  • 基于 Node.js 的 ORM(对象关系映射)工具——Sequelize介绍与使用,并举案例分析
  • 【循环神经网络】RNN介绍
  • 【容器化技术 Docker 与微服务部署】详解
  • 基于WSL在Windows下安装Ubuntu
  • C++ 设计模式:组合模式(Composite Pattern)
  • 智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之12 方案再探之3:特定于领域的模板 之2 首次尝试和遗留问题解决
  • 「Mac畅玩鸿蒙与硬件50」UI互动应用篇27 - 水果掉落小游戏
  • libvirt学习
  • 【Compose multiplatform教程24】导航与路由
  • 智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之11 方案再探之2 项目文件(修改稿1)
  • Linux2.4.20顶层Makefile文件分析
  • 我的Java-Web进阶--Spring
  • CPT203 Software Engineering 软件工程 Pt.2 敏捷方法和需求工程(中英双语)
  • 计算机的错误计算(一百九十七)
  • Kubernetes第二天
  • Vue演练场基础知识(一)
  • Wireshark和科来网络分析系统
  • 掌握大数据处理利器:Flink 知识点全面总结【上】