【CCCC】L3-018 森森美图 (30分),计算几何+判断三点共线+bfs最短路

简介: 【CCCC】L3-018 森森美图 (30分),计算几何+判断三点共线+bfs最短路

problem

L3-018 森森美图 (30分)
森森最近想让自己的朋友圈熠熠生辉,所以他决定自己写个美化照片的软件,并起名为森森美图。众所周知,在合照中美化自己的面部而不美化合照者的面部是让自己占据朋友圈高点的绝好方法,因此森森美图里当然得有这个功能。 这个功能的第一步是将自己的面部选中。森森首先计算出了一个图像中所有像素点与周围点的相似程度的分数,分数越低表示某个像素点越“像”一个轮廓边缘上的点。 森森认为,任意连续像素点的得分之和越低,表示它们组成的曲线和轮廓边缘的重合程度越高。为了选择出一个完整的面部,森森决定让用户选择面部上的两个像素点A和B,则连接这两个点的直线就将图像分为两部分,然后在这两部分中分别寻找一条从A到B且与轮廓重合程度最高的曲线,就可以拼出用户的面部了。 然而森森计算出来得分矩阵后,突然发现自己不知道怎么找到这两条曲线了,你能帮森森当上朋友圈的小王子吗?

为了解题方便,我们做出以下补充说明:

图像的左上角是坐标原点(0,0),我们假设所有像素按矩阵格式排列,其坐标均为非负整数(即横轴向右为正,纵轴向下为正)。
忽略正好位于连接A和B的直线(注意不是线段)上的像素点,即不认为这部分像素点在任何一个划分部分上,因此曲线也不能经过这部分像素点。
曲线是八连通的(即任一像素点可与其周围的8个像素连通),但为了计算准确,某像素连接对角相邻的斜向像素时,得分额外增加两个像素分数和的√
​2

​​ 倍减一。例如样例中,经过坐标为(3,1)和(4,2)的两个像素点的曲线,其得分应该是这两个像素点的分数和(2+2),再加上额外的(2+2)乘以(√
​2

​​ −1),即约为5.66。
输入格式:
输入在第一行给出两个正整数N和M(5≤N,M≤100),表示像素得分矩阵的行数和列数。

接下来N行,每行M个不大于1000的非负整数,即为像素点的分值。

最后一行给出用户选择的起始和结束像素点的坐标(X
​start
​​ ,Y
​start
​​ )和(X
​end
​​ ,Y
​end
​​ )。4个整数用空格分隔。

输出格式:
在一行中输出划分图片后找到的轮廓曲线的得分和,保留小数点后两位。注意起点和终点的得分不要重复计算。

输入样例:
6 6
9 0 1 9 9 9
9 9 1 2 2 9
9 9 2 0 2 9
9 9 1 1 2 9
9 9 3 3 1 1
9 9 9 9 9 9
2 1 5 4
输出样例:
27.04

  • 给出一个n*m的矩阵,每个点有点权
  • 求两条分散在起点s到终点t连线两边的最短点权路(可以用斜边),输出权值和

solution

  • 将矩形分成ab两边分别求最短路,转移的时候用三点共线判断是否越界即可。
  • 矩形上求最短路可以直接bfs,当然dijkstra或者spfa也区别不大。
#include<bits/stdc++.h>
using namespace std;
const int inf = 1e9+10;
const int maxn = 110;

struct point{ int x, y;  double dis;};
bool operator!=(point a, point b){return a.x!=b.x||a.y!=b.y;}
bool operator==(point a, point b){return a.x==b.x&&a.y==b.y;}

int n, m;
double sc[maxn][maxn];//分数
point s, t;
void input(){
    cin>>n>>m;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            cin>>sc[i][j];
    cin>>s.y>>s.x>>t.y>>t.x;
    s.x++;s.y++;t.x++;t.y++;
    s.dis = sc[s.x][s.y];
}

int flag;//1上半部分,0下半部分
double f[maxn][maxn]; //到i,j为止的最小值
int dir[][2]= {{0,1},{1,0},{-1,0},{0,-1},{-1,-1},{1,-1},{-1,1},{1,1}}; //上下左右+前后左右
int cross(point a,point b,point p){//三角形行列式公式,判断三点是否在一个直线上
    return (b.x-a.x)*(p.y-a.y)-(p.x-a.x)*(b.y-a.y);
}
bool check(point p){//检查p是否合法(越界)
    if(p.x<1||p.x>n||p.y<1||p.y>m)return false;//越界
    if(flag && p!=s&&p!=t && cross(s,t,p)<=0)return false;//1:上半部分但点在下面(起点终点不算)
    if(!flag && p!=s&&p!=t && cross(s,t,p)>=0)return false;//2.下半部分但点在上面
    if(p.dis>=f[p.x][p.y])return false;//不是最小值
    return true;
}
void bfs(){
    //init
    queue<point>q;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            f[i][j] = inf;
    //search
    if(check(s)){
        f[s.x][s.y] = s.dis;
        q.push(s);
    }
    while(q.size()){
        point now = q.front(); q.pop();
        point next;
        for(int i = 0; i < 8; i++){
            next.x=now.x+dir[i][0];
            next.y=now.y+dir[i][1];
            if(i<4)next.dis = f[now.x][now.y]+sc[next.x][next.y];
            else next.dis=f[now.x][now.y]+sc[next.x][next.y]+(sc[next.x][next.y]+sc[now.x][now.y])*(sqrt(2)-1);
            if(check(next)){
                f[next.x][next.y] = next.dis;
                q.push(next);
            }
        }
    }
}

int main(){
    input();
    double ans = 0;
    flag = 1; bfs(); ans += f[t.x][t.y];//搜上面
    flag = 0; bfs(); ans += f[t.x][t.y];//搜下面
    ans -= sc[s.x][s.y]+sc[t.x][t.y];//重复
    printf("%.2f\n",ans);
    return 0;
}
目录
相关文章
|
定位技术
【CCCC】L3-007 天梯地图 (30分),两次Dijkstra+路径打印(数据点2,4错因),90行最短题解
【CCCC】L3-007 天梯地图 (30分),两次Dijkstra+路径打印(数据点2,4错因),90行最短题解
133 0
|
20天前
|
存储 算法 C++
第 284 场周赛(C++ | 枚举 | 分类讨论 | 最短路 | 建反图)
【4月更文挑战第1天】- [LeetCode 6031](https://leetcode-cn.com/problems/find-all-k-distant-indices-in-an-array/):给定数组 `nums`、键值 `key` 和距离 `k`,找到所有与键值相等且与任意下标距离不超过 `k` 的下标,返回升序排序的列表。找到最小权重。
29 0
|
4月前
【每日一题Day126】LC1140石子游戏Ⅱ | 博弈dp 记忆化搜索
【每日一题Day126】LC1140石子游戏Ⅱ | 博弈dp 记忆化搜索
29 0
|
6月前
|
算法
【算法挨揍日记】day03——双指针算法_有效三角形的个数、和为s的两个数字
【算法挨揍日记】day03——双指针算法_有效三角形的个数、和为s的两个数字
35 0
|
存储
【每日一题Day95】LC1815得到新鲜甜甜圈的最多组数 | 状态压缩dp 记忆化搜索
子问题、哪些操作会影响数据:余下的甜甜圈数量left,以及剩余可以选的元素个数 cnt[x]【dfs函数的两个参数->使用状态压缩至一个int类型变量中】
89 0
【每日一题Day95】LC1815得到新鲜甜甜圈的最多组数 | 状态压缩dp 记忆化搜索
|
定位技术
【CCCC】L3-005 垃圾箱分布 (30分),Dijkstra跑n遍 = 多源最短路
【CCCC】L3-005 垃圾箱分布 (30分),Dijkstra跑n遍 = 多源最短路
100 0
|
人工智能 移动开发 算法
【CCCC】L3-032 关于深度优先搜索和逆序对的题应该不会很难吧这件事 (30分)
【CCCC】L3-032 关于深度优先搜索和逆序对的题应该不会很难吧这件事 (30分)
140 0
|
算法 C++ Python
BFS逛街算法模板-附LeetCode习题-433. 最小基因变化-广度优先搜索
BFS逛街算法模板-附LeetCode习题-433. 最小基因变化-广度优先搜索
|
算法 定位技术 Perl
|
定位技术
L3-007 天梯地图 (30 分)(两次dijkstra分别遍历)
L3-007 天梯地图 (30 分)(两次dijkstra分别遍历)
97 0