洛谷 P1355 神秘大三角

题目

判断一个点与已知三角形的位置关系。

若点在三角形内(不含边界),输出1;

若点在三角形外(不含边界),输出2;

若点在三角形边界上(不含顶点),输出3;

若点在三角形顶点上,输出4。

题解

非常简单,只要你会

解题步骤:

1.读入,因为有括号,所以我只能先用字符串读,然后慢慢转成数字。这一步注意,不要忘记数据里有三位数,要打好相应的代码

2.特判点是不是在三角形的顶点上

3.用叉积公式计算点与三角形的每条边的关系,
叉积公式:
m=((x1-x0)(y2-y0))-((x2-x0)(y1-y0))
这里写图片描述
(1)m=0,则点在三角形边上。
(2)每一次计算完一条边的m都要判断m与0的大小关系有无变化,若有变化则点在三角形外
(3)所有边都判断完后,就直接输出1

注意,1和2的顺序绝不能调换,因为假如上一次m大于0,而这一次m等于0,此时若先2,上一次m<>这一次m,程序就会判断点在三角形外

样例数据

几个比较容易错的

 (10,10)
 (30,40)
 (30,10)
 (20,25)  答案是3

 (1,1)
 (3,4)
 (1,2)
 (2,3)   答案是3

 (1,1)
 (3,4)
 (2,1)
 (2,3)   答案是2

代码

var
  aa,bb,cc,i,j:longint;
  a:array[1..4,1..2]of longint;
  s:string;

function m(x0,y0,x1,y1,x2,y2:longint):longint;
begin
  m:=((x1-x0)*(y2-y0))-((x2-x0)*(y1-y0));
  if m<0 then exit(-1);
  if m>0 then exit(1);
end;

begin
  for j:=1 to 4 do
    begin
      readln(s);
      i:=2;
      while i<length(s) do
        if s[i-1]='(' then
          while s[i]<>',' do
            begin
              a[j,1]:=a[j,1]*10+ord(s[i])-48;
              inc(i);
            end else
        if s[i-1]=',' then
          while s[i]<>')' do
            begin
              a[j,2]:=a[j,2]*10+ord(s[i])-48;
              inc(i);
            end else inc(i);
    end;
  for i:=1 to 3 do
    if (a[4,1]=a[i,1])and(a[4,2]=a[i,2]) then begin writeln('4');exit;end;
  aa:=m(a[1,1],a[1,2],a[2,1],a[2,2],a[4,1],a[4,2]);
  if aa=0 then begin writeln('3');exit;end;
  bb:=m(a[2,1],a[2,2],a[3,1],a[3,2],a[4,1],a[4,2]);
  if bb=0 then begin writeln('3');exit;end;
  if aa<>bb then begin writeln('2');exit;end;
  cc:=m(a[3,1],a[3,2],a[1,1],a[1,2],a[4,1],a[4,2]);
  if cc=0 then begin writeln('3');exit;end;
  if aa<>cc then begin writeln('2');exit;end;
  writeln('1');
end.
### 关于洛谷 P1249 最乘积问题的 C++ 解题思路 对于给定的一个正整数 `n` 和分割次数 `k`,目标是将 `n` 分割成 `k` 个部分使得这些部分的乘积最化。这个问题可以通过动态规划来解决。 #### 动态规划的状态定义 设 `dp[i][j]` 表示前 `i` 位数字分成 `j` 段所能得到的最乘积[^3]。 #### 初始化 - 对于只有一段的情况,即 `dp[i][1]` 就是从第1位到第i位组成的整个数值。 #### 状态转移方程 为了求解 `dp[i][j]` 的值,可以考虑最后一个切割位置 `p` (其中 `1 ≤ p < i`),则状态转移方程为: \[ dp[i][j]=\max(dp[p][j-1]*num(p+1,i)) \] 这里 `num(p+1,i)` 是指从第 `p+1` 到第 `i` 位所表示的子串对应的十进制数值。 #### 边界条件 当 `j=1` 或者 `i=j` 时,显然不需要进一步划分,因此可以直接赋初值;其他情况下通过上述公式计算得出结果。 下面是具体的代码实现: ```cpp #include<iostream> #include<string> using namespace std; const int MAX_N = 50; string s; long long f[MAX_N][MAX_N], num[MAX_N][MAX_N]; // 计算字符串s中从l到r之间的数字转换成long long型 void calc_num() { for (int l = 0; l < s.size(); ++l) for (int r = l; r < s.size(); ++r) { if (!l && !r) num[l][r] = s[l]-&#39;0&#39;; else num[l][r] = num[l][r-1]*10+s[r]-&#39;0&#39;; } } int main(){ int N, K; cin >> N >> K >> s; // 预处理每一段的数值 calc_num(); // 初始化边界情况 for(int i = 0; i<s.length();++i){ f[i+1][1]=num[0][i]; f[i+1][i+1]=f[i][i]*10+(s[i]-&#39;0&#39;); } // 填表过程 for(int j = 2;j<=K;++j)//枚举段数 for(int i = j;i<N;++i)//枚举终点 for(int k = j-1;k<i;++k)// 枚举上一次切分的位置 f[i][j]=max(f[i][j],f[k][j-1]*num[k][i]); cout << f[N-1][K]<<endl; } ``` 这段代码实现了基于动态规划的方法来寻找最优解,并且能够有效地处理高精度运算的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值