Summer day 3

早上没啥事,分析下昨天一直WA的题目,结果还是WA,没明白为啥。

Uva815 洪水
题目大意 给出区域(Region)的长,宽,以10m为单位,再给出各块海拔和洪水体积,求洪水水位高度。区域四周无限高,因此可能出现100%覆盖区域的情况。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

double a[1001];
double vol;
int n, m;

void solve()
{
    double sum_delta_h = 0, rate, hi, prev;
    int flag = 0;
    for(int i = 1; i<n*m; i++)
    {
        sum_delta_h += (a[i]-a[i-1])*double(i);
        if(sum_delta_h*100.>=vol)
        {
            flag = 1;
            prev = (sum_delta_h - (a[i]-a[i-1])*double(i))*100.;
            rate = double(i*100.0)/double(n*m);
            hi = (vol - prev)/(100*i);
            hi = hi+a[i-1];
            break;
        }
    }
    if(flag == 0)
    {
        hi = (vol - sum_delta_h)/(100*n*m);
            hi = hi+a[n*m-1];
        rate = 100.0;
    }
    printf("Water level is %.2lf meters.\n%.2lf percent of the region is under water.\n",hi, rate);
}

int main()
{
    int kase = 0;
    while(scanf("%d%d",&m, &n)!=EOF)
    {
        if(m+n == 0)
            break;
        for(int i = 0; i<n*m; i++)
            scanf("%lf", &a[i]);
        scanf("%lf",&vol);
        sort(a, a+n*m);
        printf("Region %d\n",++kase);
        solve();
        printf("\n");
        memset(a, 0, sizeof(a));
    }
    return 0;
}

首先讲思路。这是一道模拟/数学题,实现起来并不难,但是边界和特殊情况要细心考虑。

  1. 读入。
  2. 初始化,排序。既然水位平,就可以排序解。
  3. 用循环找临界的块。
    具体找法就是利用高度差之和(sum_delta_h)乘100来逐个记录体积在比较,具体操作见solve()。
  4. 输出。

    Uva 253 Cube painting

    给出两个着三色的立方体,判断是否等价(即旋转)。
    这道题昨天没有A,代码很长最后没耐心调试,觉得这样做效率好低。今天看了看题解,发现一个简洁高效的解法,当时我没有震惊。


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=20;
char str[N],str1[N],str2[N];
int dir[6][6]={ {0,1,2,3,4,5},{1,5,2,3,0,4},{2,1,5,0,4,3},{3,1,0,5,4,2},
                {4,0,2,3,5,1},{5,4,2,3,1,0} };
bool fun();
int main()
{
    while(scanf("%s",str)!=EOF)
    {
        for(int i=0;i<6;i++) str1[i]=str[i];
        for(int i=0;i<6;i++) str2[i]=str[i+6];
        if(fun()) puts("TRUE");
        else puts("FALSE");
    }
    return 0;
}
bool fun()
{
    char temp[N]={0};
    for(int i=0;i<6;i++)
    {
        for(int j=0;j<6;j++)
        {
            temp[j]=str1[dir[i][j]];
        }
        for(int j=0;j<4;j++)
        {
            char cha;
            cha=temp[1];
            temp[1]=temp[2];
            temp[2]=temp[4];
            temp[4]=temp[3];
            temp[3]=cha;
            if(strcmp(temp,str2)==0) return true;
        }
    }
    return false;
}

这个数组用的很精妙,表示了把各个面旋转到第一面时其他面的分布,再进行旋转比对。
我今天果然和WA有缘,下午练习赛又是一道死活过不了的WA,HDU 5578,青蛙的朋友。状态查找不好维护。

HDU 5538,配了个MC的图,并不能改变这道题的狗血背景。 求给出立方堆积的表面积。

一次过。思路是对每个坐标求它与隔壁的差来确定它“拥有”的面积,同时从(1,1)开始让边界不用再判断了。

#include<cstdio>
#include<cstring>

int map[55][55];
int n, m;

int check(int i, int j)
{
    int area = 0;
    if(map[i][j]-map[i-1][j]>0)
        area+=(map[i][j]-map[i-1][j]);
    if(map[i][j]-map[i+1][j]>0)
        area+=(map[i][j]-map[i+1][j]);
    if(map[i][j]-map[i][j+1]>0)
        area+=(map[i][j]-map[i][j+1]);
    if(map[i][j]-map[i][j-1]>0)
        area+=(map[i][j]-map[i][j-1]);
    if(map[i][j]>0)
        area++;
    return area;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int ans = 0;
        memset(map, 0, sizeof(map));
        scanf("%d%d",&n, &m);
        for(int i = 1; i<=n; i++)
            for(int j = 1; j<=m; j++)
                scanf("%d",&map[i][j]);
        for(int i = 1; i<=n; i++)
            for(int j = 1; j<=m; j++)
            {
                ans+=check(i, j);
            }
        printf("%d\n",ans);
    }
    return 0;
}

晚上准备看看书和WA的题解。三点一线生活基本形成,希望周末能有个大改变(误)。

# 题目重述 在边长为160公里的正方形空域(顶点为$(0,0)$、$(160,0)$、$(160,160)$、$(0,160)$)中,现有5架飞机正在飞行,另有一架新飞机从$(0,0)$以方向角$52^\circ$进入。所有飞机速度均为800 km/h。 要求: 1. 任意两架飞机之间的最小距离必须大于8 km; 2. 每架飞机的方向角调整幅度不超过$30^\circ$; 3. 新进入飞机在边界时与区域内飞机距离大于60 km(已满足); 4. 最多考虑6架飞机; 5. 不考虑飞机离开区域后的情况; 6. 输出调整后的方向角,误差不超过$0.01^\circ$,且总调整量尽可能小。 请建立数学模型并使用群智能优化算法求解。 --- # 详解 本问题是一个典型的**动态避障约束优化问题**,目标是最小化方向角调整总量,在满足飞行安全的前提下实现无碰撞航路规划。 ## 1. 数学建模 ### (1)变量定义 设第$i$架飞机的调整量为$\Delta\theta_i$,则其实际飞行方向为: $$ \theta_i&#39; = \theta_i + \Delta\theta_i, \quad \text{其中 } |\Delta\theta_i| \leq 30^\circ $$ ### (2)位置函数(时间$t$小时后) $$ x_i(t) = x_i + 800t \cdot \cos(\theta_i&#39;\cdot\pi/180) $$ $$ y_i(t) = y_i + 800t \cdot \sin(\theta_i&#39;\cdot\pi/180) $$ ### (3)两机间距 对任意$i < j$,有: $$ d_{ij}(t) = \sqrt{(x_i(t)-x_j(t))^2 + (y_i(t)-y_j(t))^2} $$ 我们需保证在预测时间段内(如$[0, T]$,取$T=1$小时),所有$d_{ij}(t) > 8$ ### (4)目标函数 最小化总调整量(使用绝对值之和): $$ \min \sum_{i=1}^{6} |\Delta\theta_i| $$ ### (5)约束条件 - $|\Delta\theta_i| \leq 30^\circ$ - $\forall i<j, \forall t \in [0,1],\ d_{ij}(t) > 8$ - 初始时刻新飞机与其他飞机距离 $>60$ km(原始数据满足) 由于连续时间难以遍历,采用**离散化采样**:将$[0,1]$分为60个点(每分钟一次) --- ## 2. 解法选择:粒子群优化算法(PSO) PSO适合解决此类高维、非线性、带约束的优化问题。每个粒子表示一组方向角调整方案。 --- # 代码实现(Python + NumPy + Matplotlib 可视化) ```python import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import Circle # ================= 参数设置 ================= N_PARTICLES = 50 # 粒子数量 MAX_ITER = 200 # 最大迭代次数 DIM = 6 # 维度:6架飞机的角度调整 V_MIN, V_MAX = -5, 5 # 粒子速度范围 UB = 30 # 上界 LB = -30 # 下界 W = 0.7 # 惯性权重 C1 = 1.5 # 个体学习因子 C2 = 1.5 # 群体学习因子 T_STEPS = 60 # 时间步数(模拟未来1小时,每分钟一步) PENALTY = 1e5 # 约束违反惩罚项 # 初始数据 [x, y, theta_deg] planes = np.array([ [150, 40, 243], [85, 85, 236], [150, 155, 220.5], [145, 50, 159], [130, 150, 230], [0, 0, 52] # 新进入飞机 ]) speed = 800 # km/h def simulate_trajectory(delta_theta, t_hours): """ 计算所有飞机在t时刻的位置 delta_theta: (6,) 调整量数组 t_hours: float 或 array of floats 返回: (6, 2) 位置矩阵 """ theta_prime = np.radians(planes[:, 2] + delta_theta) cos_t = np.cos(theta_prime) sin_t = np.sin(theta_prime) x = planes[:, 0][:, None] + speed * t_hours * cos_t[:, None] y = planes[:, 1][:, None] + speed * t_hours * sin_t[:, None] return np.stack((x, y), axis=-1) def fitness(individual): """ 适应度函数 individual: (6,) 当前调整量 返回: scalar fitness value (越小越好) """ # 检查是否超出调整限制 if np.any(individual < LB) or np.any(individual > UB): return np.inf # 时间序列: 0 到 1 小时,共 T_STEPS 步 t_vec = np.linspace(0, 1, T_STEPS) # 获取所有时刻所有飞机的位置 traj = simulate_trajectory(individual, t_vec) # shape: (6, T_STEPS, 2) min_dist = np.inf for i in range(6): for j in range(i+1, 6): dist = np.sqrt(np.sum((traj[i] - traj[j])**2, axis=1)) # 各时间点距离 min_dist = min(min_dist, np.min(dist)) # 目标:最小化调整量;约束:最小距离 > 8 obj = np.sum(np.abs(individual)) if min_dist <= 8: penalty = PENALTY * (8 - min_dist)**2 else: penalty = 0 return obj + penalty # ================= PSO 主循环 ================= # 初始化粒子群 np.random.seed(42) X = np.random.uniform(LB, UB, (N_PARTICLES, DIM)) # 位置 V = np.random.uniform(V_MIN, V_MAX, (N_PARTICLES, DIM)) # 速度 pbest_pos = X.copy() pbest_fit = np.array([fitness(X[i]) for i in range(N_PARTICLES)]) gbest_idx = np.argmin(pbest_fit) gbest_pos = pbest_pos[gbest_idx].copy() gbest_fit = pbest_fit[gbest_idx] # 迭代优化 for iter in range(MAX_ITER): for i in range(N_PARTICLES): # 更新速度 r1, r2 = np.random.rand(DIM), np.random.rand(DIM) V[i] = W*V[i] + C1*r1*(pbest_pos[i] - X[i]) + C2*r2*(gbest_pos - X[i]) V[i] = np.clip(V[i], V_MIN, V_MAX) # 更新位置 X[i] += V[i] X[i] = np.clip(X[i], LB, UB) # 更新个体最优 fit = fitness(X[i]) if fit < pbest_fit[i]: pbest_pos[i] = X[i].copy() pbest_fit[i] = fit # 更新全局最优 if fit < gbest_fit: gbest_pos = X[i].copy() gbest_fit = fit if iter % 50 == 0: print(f"Iter {iter}, Best Fitness: {gbest_fit:.4f}") # 输出最终结果 final_adjustment = np.round(gbest_pos, 2) final_angles = planes[:, 2] + final_adjustment print("\n=== 最终调整方案 ===") print("编号\t原方向角\t调整量\t\t新方向角") for idx in range(6): print(f"{idx+1}\t{planes[idx,2]:.1f}\t\t{final_adjustment[idx]:+.2f}\t\t{final_angles[idx]:.2f}") # 验证最小距离 def check_min_distance(delta_theta): t_vec = np.linspace(0, 1, T_STEPS) traj = simulate_trajectory(delta_theta, t_vec) min_d = np.inf for i in range(6): for j in range(i+1, 6): d = np.sqrt(np.sum((traj[i] - traj[j])**2, axis=1)) min_d = min(min_d, np.min(d)) return min_d min_separation = check_min_distance(final_adjustment) print(f"\n所有飞机间的最小距离: {min_separation:.2f} km (>8 km 才安全)") assert min_separation > 8, "❌ 存在碰撞风险!" print("✅ 安全飞行方案已找到") # ================= 可视化轨迹 ================= def plot_trajectories(delta_theta): plt.figure(figsize=(10, 10)) t_vec = np.linspace(0, 1, 60) traj = simulate_trajectory(delta_theta, t_vec) colors = [&#39;r&#39;, &#39;g&#39;, &#39;b&#39;, &#39;c&#39;, &#39;m&#39;, &#39;orange&#39;] labels = [f&#39;Plane {i+1}&#39; for i in range(6)] for i in range(6): x_traj = traj[i, :, 0] y_traj = traj[i, :, 1] plt.plot(x_traj, y_traj, c=colors[i], label=labels[i], linewidth=2) plt.scatter(x_traj[0], y_traj[0], c=colors[i], s=50, zorder=5) # 添加方向箭头 dx = x_traj[5] - x_traj[0] dy = y_traj[5] - y_traj[0] plt.arrow(x_traj[0], y_traj[0], dx*2, dy*2, head_width=3, fc=colors[i], ec=colors[i]) # 绘制安全圆(可选) for i in range(6): circle = Circle((traj[i, 0, 0], traj[i, 0, 1]), radius=4, color=colors[i], alpha=0.2) plt.gca().add_patch(circle) plt.xlim(0, 160) plt.ylim(0, 160) plt.xlabel(&#39;X (km)&#39;) plt.ylabel(&#39;Y (km)&#39;) plt.title(&#39;Flight Paths After Adjustment\n(Arrows show initial direction)&#39;) plt.legend() plt.grid(True, linestyle=&#39;--&#39;, alpha=0.5) plt.axis(&#39;equal&#39;) plt.tight_layout() plt.show() # 是否显示可视化? # plot_trajectories(final_adjustment) ``` --- # 知识点 - **粒子群优化算法(PSO)**:一种基于群体寻优的启发式算法,通过跟踪个体与全局最优更新粒子状态。 - **运动学建模**:利用三角函数构建匀速直线运动轨迹,实现飞机位置随时间演化。 - **约束处理与罚函数法**:将硬约束转化为目标函数中的惩罚项,便于智能算法求解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值