匹配问题 dp预处理
来源:互联网 发布:sony xperia xz1 知乎 编辑:程序博客网 时间:2024/06/08 05:43
关键词:dp预处理:排序
题意:x轴上n个点与m个点之间进行匹配,保证1)n每个点都只能匹配一次2)m每个点都得有匹配对象(m<=n),已知两两点之间的匹配代价=坐标差得绝对值,求满足条件的最小匹配代价
解法:
失误:没有充分利用条件的特殊性:在x轴上!因此可以先把n个点和m个点分别在坐标轴上进行排序。
可以观察到连个端点之间一定相互匹配!
结论:x1<=x2,y1<=y2,则|x1-y1|+|x2-y2|<|x1-y2|+|x2-y1|
证明:简单处理一下就可以证出,略去
所以可以得到dp解法如下:
dp[i][j]:n个点中的前i个匹配m个点中的前j个的最小代价
dp[i][j]=min(dp[i-1][j-1],dp[i-1][j])+abs(pos1[i]-pos2[j])
注意:
1.long long范围内的INF1使用 0x0fffffffffffffff (15个f,9*INF超越LL最大值)
2.int范围内的INF2使用0x3f3f3f3f(INF2*3超越INT最大值)
拓展1:改成求匹配代价最大值,如何求解?
解法:由上述绝对值不等式可知,排好序后m个点中的最大值一定与n个点中的最小值进行匹配,否则匹配代价一定还可以增大
因此只需要把m个点从小到大排列,n个点从大到小排列,dp状态转移方程中的min改为max即可!
拓展2:改成二维平面内的坐标点,匹配代价是曼哈顿距离,如何求解最小匹配值?
#include<stdio.h>#include<iostream>#include<string.h>#include<algorithm>#define mem(a,b) memset(a,sizeof(a),b)#define ll long long#define MP make_pairusing namespace std;typedef long long lld;const lld INF = 0x0fffffffffffffff ;const int maxn = 4000+10;int n,m;struct Node{ int id; long long pos;};bool cmp(Node a,Node b){ return a.pos<b.pos;}Node que[maxn],pos[maxn];long long dp[maxn];bool path[maxn][maxn];int match[maxn];void print(int n,int m){ if(n==1) { match[que[1].id]=pos[1].id; return; } if(path[n][m]==0){ print(n-1,m); } else if(path[n][m]==1){ print(n-1,m-1); } match[que[n].id]=pos[m].id;}int abs(int a){ if(a<0) return -a; return a;}int main(){ //freopen("a.txt","r",stdin); while(scanf("%d",&n)!=EOF){ for(int i=1;i<=n;i++) { scanf("%lld",&que[i].pos); que[i].id=i; } scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%lld",&pos[i].pos); pos[i].id=i; } sort(que+1,que+n+1,cmp); sort(pos+1,pos+m+1,cmp); for(int j=0;j<=m;j++) dp[j]=INF; dp[1]=abs(que[1].pos-pos[1].pos); for(int i=2;i<=n;i++){ for(int j=min(m,i);j>=1;j--){ if(dp[j]<=dp[j-1]){ dp[j]=dp[j]+abs(que[i].pos-pos[j].pos); path[i][j]=0;} else { dp[j]=dp[j-1]+abs(que[i].pos-pos[j].pos); path[i][j]=1; } } } printf("%lld\n",dp[m]); print(n,m); for(int i=1;i<n;i++) printf("%d ",match[i]); printf("%d\n",match[n]); } return 0;}
0 0
- 匹配问题 dp预处理
- 【dp】正则表达式匹配问题
- [dp]Search 字符串匹配问题
- NYOJ15 - UVA1626 括号匹配问题(区间dp)
- NYOJ15 - UVA1626 括号匹配问题(dp)
- 集合DP 点集匹配问题
- BZOJ 4352 预处理 + DP
- 九度OJ 1153:括号匹配问题 (DP)
- vijos 1892 树上的最大匹配问题 树形dp
- HDU 5617 多维dp降维问题,回文串匹配
- 一类关于括号匹配的问题 区间dp
- DZY Loves Sequences 预处理 dp
- hdu 4791 dp预处理+二分
- HDU 4455 Substrings(预处理+dp)
- lightoj 1326 - Race dp+预处理
- FZU 2204 7 dp+预处理
- FZU 2200 cleaning dp+预处理
- 【bzoj4043】【Cerc2014】【Vocabulary】【dp+预处理】
- 排列组合。
- 2015/4/21 深入理解Android卷I:第3章:深入理解init
- java的(PO,VO,TO,BO,DAO,POJO)解释
- 30 31 php phpexcel学习
- 管理杂谈(三)--必须的思想
- 匹配问题 dp预处理
- cocos2d-x 3.4 windows 环境配置
- 小米路由
- 基于LinkedHashMap实现LRU缓存调度算法原理
- 数字签名是什么?
- Celery 和 RabbitMQ
- [cc]18.9中位数
- C++11,使简单的事情简单
- Mysql日志文件默认路径的修改方法(Mysql binlog relocate)