uva :10123 - No Tipping(dfs + 几何力距 )
题目:uva :10123 - No Tipping
题目大意:给出l, m, n 分别表示 长度为l 的杠杆, 重量为 m, 有n个物体放在上方。问每次从上面挑选一个物品移除,是否能使杠杆继续平衡。这个过程中都可以的话,就输出移除顺序(不唯一) 否则就输出 impossible ,一开始,这个杠杆就不平衡的情况也会是有的。因为杠杆也是有重量的。
解题思路;
1、这题先前我就不明白什么怎么样的情况下,双支撑点的杠杆不平横,后面看了别人的报告才明白。
首先 我这里有两个支撑点 (1, 2) 左边的为1. 然后1支撑点的左力距为wl1.同理还有wr1, wl2, wr2. 有1个支撑点的力距的值可以比没有支撑点的力距大,因为多个支撑点支撑重量。所以 这里不平横情况 ( wl1 > wr1 || wr2 > wl2).
2、这题还有时间的问题,直接去dfs是会超时的。所以这里就需要优化。
首先放在两个支撑点中间的物体会使得这个杠杆更加的平衡,因此,这样的物体可以最后移除。然后将力距分左右从小到大的排序。因为要使得移除的任何一个过程都需要平衡,所以问题可以转换为把一个一个物体放到一开始为空的杠杆上的状态和顺序,最后逆向输出。物体一个一个放的话,当然是力距小比较不容易发生失衡的现象。然后左边的物体从例力距小的开始放,如果不能放就换放右边的力距小的物体。如果两边都不能放就说明是impossible。
注意:这题中间dfs需要考虑仔细点,例如如何判断两边都不能放的情况,如果一边都放完的情况,还有这边放一些去另外一边的情况。
还有两支撑点间的物体虽然dfs不需要考虑,但是他们的力距需要加到总的力距上。他们的加入会使得杠杆更加平衡,能支撑更多的物体。
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
using namespace std;const int N = 30;
int l, m, n, ans[N][2], path[3], cnt[3];
int flag;
double wl1, wl2, wr1, wr2;struct OB {int w, l;
} obl[N], obr[N], obm[N];bool cmp (const OB & x,const OB &y) {if (abs (x.l * x.w) < abs (y.l * y.w))return true;return false;
}void solve (int dir, int cur, int bo) {if (cur >= n) {flag = 1;return;}if (dir == 0) {for (int i = path[dir]; i < cnt[dir]; i++) {
// printf ("%.3lf %.3lf\n", wl1 + ( -3 - obl[i].l) * obl[i].w, wr1);if (wl1 + (-3 - obl[i].l) * obl[i].w > wr1) {if (bo) {flag = -1;return;}path[dir] = i;solve( 2 - dir, cur, bo + 1);if (flag)return;} else {ans[cur][0] = obl[i].l;ans[cur][1] = obl[i].w;wl1 += (-3 - obl[i].l) * obl[i].w;wl2 += (3 - obl[i].l) * obl[i].w;path[dir] = i + 1;cur++;bo = 0;}}if (path[2 - dir] <= cnt[2 - dir]) solve (2 - dir, cur, bo);} else {for (int i = path[dir]; i < cnt[dir]; i++) {if (wr2 + (obr[i].l - 3) * obr[i].w > wl2) {if (bo) {flag = -1;return;}path[dir] = i;solve (2 - dir, cur, bo + 1);if (flag)return;} else {ans[cur][0] = obr[i].l;ans[cur][1] = obr[i].w;wr1 += (obr[i].l + 3) * obr[i].w;wr2 += (obr[i].l - 3) * obr[i].w;path[dir] = i + 1;cur++;bo = 0;}}if (path[2 - dir] <= cnt[2 - dir])solve (2 - dir, cur, bo);}if (flag)return;
}int main () {int p, w, t = 0;while (scanf ("%d%d%d", &l, &m, &n), l || m || n) {wl1 = wr2 = (l - 3.0) * (l - 3.0) * m / l / 4.0;wl2 = wr1 = (l + 3.0) * (l + 3.0) * m / l / 4.0;
// printf ("wl1 = %.3lfwr1 = %.3lf\n", wl1, wr1);memset (cnt, 0, sizeof (cnt));for (int i = 0; i < n; i++) {scanf ("%d%d", &p, &w);p = p * 2;if (p <= 3 && p >= -3){obm[cnt[1]].w = w;obm[cnt[1]].l = p;cnt[1]++;} else {if (p > 3) {obr[cnt[2]].w = w;obr[cnt[2]].l = p;cnt[2]++;} else {obl[cnt[0]].w = w;obl[cnt[0]].l = p;cnt[0]++;}}}sort (obl, obl + cnt[0], cmp);sort (obr, obr + cnt[2], cmp);memset (path, 0, sizeof (path));for (int i = 0; i < cnt[1]; i++) {wr1 += (obm[i].l + 3) * obm[i].w;wl2 += (3 - obm[i].l) * obm[i].w;}printf ("Case %d:\n", ++t);flag = 0;if (wl1 <= wr1 && wr2 <= wl2) {solve (0, cnt[1], 0);}if (flag != 1)printf ("Impossible\n");else {for (int i = n - 1; i >= cnt[1]; i--)printf ("%d %d\n", ans[i][0]/2, ans[i][1]);if (cnt[1] - 1 >= 0)for (int i = cnt[1] - 1; i >= 0; i--)printf ("%d %d\n", obm[i].l/2, obm[i].w);}}return 0;
}
uva :10123 - No Tipping(dfs + 几何力距 )相关推荐
- uva 12253 - Simple Encryption(dfs)
题目链接:uva 12253 - Simple Encryption 题目大意:给定K1.求一个12位的K2,使得KK21=K2%1012 解题思路:按位枚举,不且借用用高速幂取模推断结果. #inc ...
- [uva]AncientMessages象形文字识别 (dfs求连通块)
非常有趣的一道题目,大意是给你六种符号的16进制文本,让你转化成二进制并识别出来 代码实现上参考了//http://blog.csdn.net/u012139398/article/details/3 ...
- UVA - 11437 Triangle Fun(简单几何)
题目链接:点击查看 题目大意:给出三个顶点A,B,C组成三角形,如题目中的图片所示,规定D,E,F分别为三条边的三等分点,现在要求三角形RPQ的面积 题目分析:利用向量先求出DEF三点,再利用线段相交 ...
- MATLAB把型线图画静水力曲线,静水力曲线图
下面具体介绍各静水力曲线的名称和使用方法: 1.排水体积曲线(Volume of Molded Displacement Curve) 表示船舶的型排水体积(m3)随平均型吃水增加而增大的规律: 2. ...
- 【算法分析与设计】DFS与BFS的区别
广度优先遍历(BFS)算法先访问所有最近的子结点,然后再向下访问. 深度优先遍历(DFS)算法先沿着一条路不断向下访问,然后再访问同级结点. 从基本的定义和实现思路上看,DFS和BFS都是递归的. B ...
- 初学者acm的练习题指南
上机练习题参考题 忘了在哪找的啦~~希望对大家有帮助呦 <!--[if !supportLists]-->1. <!--[endif]-->Programming Bas ...
- 提取了下刘汝佳推荐的题号...
今天闲来没事上uva oj提取了下刘汝佳推荐的acm题号,原始数据如下: Volume 0. Getting Started 10055 - Hashmat the Brave Warrior ...
- 浅析步进电机常见的三种驱动方式
步进电机是一种作为控制用的特种电机, 它的旋转是以固定的角度(称为"步距角")一步一步运行的, 其特点是没有积累误差( 为100%), 所以广泛应用于各种开环控制. 步进电机的运 ...
- 网络基本命令[转载]
标题: 网络基本命令 日期: 2002-11-09 内容: ping 一.基础知识: ping-TCP/IP协议中最有用的命令之一 它给另一个系统发送一系列的数据包,该系统本身又发回一个响应,这条实用 ...
最新文章
- python装饰器作用-Python装饰器的通俗理解
- Taro+react开发(78):taro生命周期render
- 前端学习(2523):展示博客并添加方法
- 送书 | 推荐一个可能是最全的Venn图一站式绘制工具
- STM32使用DMA发送串口数据
- Android让控件位于底部
- python分布式计算框架_分布式计算框架Spark
- 回文数判断python五位数_Python【习题】回文数:判断一个数是否是回文数
- 跟我一起学Windows Workflow Foundation(4)-----使用Listen,Delay,和其他envnt-based定制活动...
- 基于visual Studio2013解决C语言竞赛题之1064互质数差1验证
- 北京联通IPTV机顶盒管理密码
- 阿酷三合一版_阿酷插件下载|3dmax阿酷插件下载 v3.2 开源版 - 比克尔下载
- git 终端配置mac(udacity)
- 粒子滤波的通俗解释,傻子的搜寻策略--我的理解_拔剑-浆糊的传说_新浪博客
- oracle如何禁用job,Oracle中如何停用JOB及如何使用JOB
- Python数据分析与实战挖掘
- Box2D 中文手册
- 【Android 数据业务解析】APN参数创建
- bzoj 3811: 玛里苟斯【线性基+期望dp】
- ArcGIS基础实验操作100例--实验21按区域修改栅格值