斜率这个概率很简单,描述了几何线的变化。恰当的运用它能让整个思维变得开阔。
51nod 1451 合法三角形
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1451
不用三边长关系来判断能否构成三角形,直接考虑各个点的组合。
最简单的情况下,选三个不同的点可以组成三角形.
一般情况下,存在三点共线的情况,除去它们。(注:斜率相等不一定共线啊,但是共线一定斜率相等)
抓住共线一定斜率相等的特点不断排除不该有的三角形。
拓展:三重循环的执行次数等于 n(n-1)(n-2)/6,推广,一个长度为n的m重循环的执行次数就是:
(组合学的角度更好理解)
codeforce 514B - Han Solo and Lazer Gun
http://codeforces.com/problemset/problem/514/B
hdu 4310 Hero
http://acm.hdu.edu.cn/showproblem.php?pid=4310
大意:有n个怪,英雄只能一次攻击一个怪,对其造成1点的伤害。当攻击的时候所有的怪也来攻击英雄,对Hero造成所有DPS的和的伤害(可以理解成怪的攻击力的和)。当怪的HP值(可以理解为防御力)变成0时,它被消灭。问怎样设计可以保证消灭所有的怪,且自己的伤害最小? 输出最小值。
分析:也含有比值(斜率的思想)。不过要处理一下,
lydsy 2659 [Beijing wc2012]算不出的算式
k=q/p和k=p/q的两条直线关于y=x对称,
刚好可以看做小矩形的一部分S
51nod 1451 合法三角形
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1451
有n个不同的点,问有多少组三元组能构成面积非0的三角形。
Input
单组测试数据。
第一行一个整数n (1 ≤ n ≤ 2000),表示点的数目。
接下来n行,每行包含两个整数 xi, yi ( -100 ≤ xi, yi ≤ 100),表示第i个点的坐标。输入保证点是两两不同的。
Output
输出合法的三角形数目。
不用三边长关系来判断能否构成三角形,直接考虑各个点的组合。
最简单的情况下,选三个不同的点可以组成三角形.
一般情况下,存在三点共线的情况,除去它们。(注:斜率相等不一定共线啊,但是共线一定斜率相等)
抓住共线一定斜率相等的特点不断排除不该有的三角形。
拓展:三重循环的执行次数等于 n(n-1)(n-2)/6,推广,一个长度为n的m重循环的执行次数就是:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=2e3+10,M=4e6+10;
const double eps=1e-7;
typedef long long LL;
struct point{
double x,y;
}p[N];
double k[M];
double getk(point a,point b){
if(a.x==b.x) return 400; // 正无穷
return (b.y-a.y)/(b.x-a.x);
}
int cmp(double a,double b){
return a-b<-eps;
}
int main()
{
//freopen("cin.txt","r",stdin);
LL n;
while(cin>>n){
for(int i=0;i<n;i++){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
LL ans=n*(n-1)*(n-2)/6;
int cnt=0;
k[0]=-800;
for(int i=0;i<n;i++){
cnt=0;
for(int j=i+1;j<n;j++){
k[++cnt]=getk(p[i],p[j]);
}
sort(k+1,k+cnt+1,cmp);
LL rp=1;
for(int j=1;j<=cnt;j++){
if(fabs(k[j-1]-k[j])<eps) rp++;
else {
ans=ans-rp*(rp-1)/2;
rp=1;
}
}
ans=ans-rp*(rp-1)/2;
}
printf("%lld\n",ans);
}
return 0;
}
codeforce 514B - Han Solo and Lazer Gun
http://codeforces.com/problemset/problem/514/B
大意:求解
所有点过特定点产生多少条直线
分析:用斜率计算,借助STL set
#include <iostream>
#include <cstdio>
#include <cmath>
#include <set>
using namespace std;
const double PI=acos(-1.0);
const int N=1e3+10;
struct point{
int x,y;
}p[N];
double k[N];
int main()
{
double INF=tan(PI/2);
int n,x0,y0;
while(~scanf("%d%d%d",&n,&x0,&y0)){
int top=0;
for(int i=0;i<n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
if(p[i].x==x0) k[top++]=INF;
else k[top++]=(p[i].y-y0)*1.0/(p[i].x-x0);
}
set<double> mp(k,k+top);
printf("%d\n",mp.size());
}
return 0;
}
hdu 4310 Hero
http://acm.hdu.edu.cn/showproblem.php?pid=4310
大意:有n个怪,英雄只能一次攻击一个怪,对其造成1点的伤害。当攻击的时候所有的怪也来攻击英雄,对Hero造成所有DPS的和的伤害(可以理解成怪的攻击力的和)。当怪的HP值(可以理解为防御力)变成0时,它被消灭。问怎样设计可以保证消灭所有的怪,且自己的伤害最小? 输出最小值。
分析:也含有比值(斜率的思想)。不过要处理一下,
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node{
int d,h;
}p[25];
int cmp(node t1,node t2){
return t1.d*t2.h>t1.h*t2.d;
}
int main()
{
int n;
while(cin>>n){
for(int i=0;i<n;i++){
scanf("%d%d",&p[i].d,&p[i].h);
}
sort(p,p+n,cmp);
int ans=0,sum=0;
for(int i=0;i<n;i++){
sum=0;
for(int j=i;j<n;j++){
sum+=p[j].d;
}
ans+=sum*p[i].h;
}
printf("%d\n",ans);
}
return 0;
}
lydsy 2659 [Beijing wc2012]算不出的算式
大意:求解式子
其中p和q是两个奇质数
分析:数形结合
所以,一般情况下和的结果就是小矩形的面积。
但是当p=q时,向下取整就是本身,所以还要再加上对角线段的长一次
但是当p=q时,向下取整就是本身,所以还要再加上对角线段的长一次
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
int main()
{
LL p,q;
while(~scanf("%lld %lld",&p,&q)){
LL ans=(p/2)*(q/2);
if(p==q) ans=ans+p/2; //再加上一次直线上的点
printf("%lld\n",ans);
}
return 0;
}