【动态规划】Crossed Matchings
来源:互联网 发布:php 工厂模式 实例 编辑:程序博客网 时间:2024/04/19 09:09
Crossed Matchings
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 2079 Accepted: 1326
Description
There are two rows of positive integer numbers. We can draw one line segment between any two equal numbers, with values r, if one of them is located in the first row and the other one is located in the second row. We call this line segment an r-matching segment. The following figure shows a 3-matching and a 2-matching segment.
We want to find the maximum number of matching segments possible to draw for the given input, such that:
1. Each a-matching segment should cross exactly one b-matching segment, where a != b .
2. No two matching segments can be drawn from a number. For example, the following matchings are not allowed.
Write a program to compute the maximum number of matching segments for the input data. Note that this number is always even.
We want to find the maximum number of matching segments possible to draw for the given input, such that:
1. Each a-matching segment should cross exactly one b-matching segment, where a != b .
2. No two matching segments can be drawn from a number. For example, the following matchings are not allowed.
Write a program to compute the maximum number of matching segments for the input data. Note that this number is always even.
Input
The first line of the input is the number M, which is the number of test cases (1 <= M <= 10). Each test case has three lines. The first line contains N1 and N2, the number of integers on the first and the second row respectively. The next line contains N1 integers which are the numbers on the first row. The third line contains N2 integers which are the numbers on the second row. All numbers are positive integers less than 100.
Output
Output should have one separate line for each test case. The maximum number of matching segments for each test case should be written in one separate line.
Sample Input
36 61 3 1 3 1 33 1 3 1 3 14 41 1 3 3 1 1 3 3 12 111 2 3 3 2 4 1 5 1 3 5 103 1 2 3 2 4 12 1 5 5 3
Sample Output
608
Source
Tehran 1999
这是一道我越优化越慢的题。。。
朴素打了一会儿直接就过了。。。
优化了半天,结果更慢了。。。
这是一道我越优化越慢的题。。。
朴素打了一会儿直接就过了。。。
优化了半天,结果更慢了。。。
正常的是枚举最后一X,但是我比较菜嘛。。我枚举最后半X。。
如果是后半X则由前半X推过来。
如果是前半X则由前面任一后半X推过来。
方程比较菜。。。
优化到O(N^4)的最快的程序。(其实本来就是O(N^4),只是我比较菜,一开始打出来是O(N^5),后来把K滚动了)
#include <cstdio>#define MAX(a,b) ((a)>(b)?(a):(b))#define MIN(a,b) ((a)<(b)?(a):(b))long num1[110];long num2[110];long f[110][110][110];int main(){freopen("cm.in","r",stdin);freopen("cm.out","w",stdout);long M;scanf("%ld",&M);while (M--){long N1;long N2;scanf("%ld%ld",&N1,&N2);for (long i=1;i<N1+1;i++)for (long j=1;j<N2+1;j++)for (long k=0;k<2;k++)f[i][j][k] = 0;for (long i=1;i<N1+1;i++)scanf("%ld",num1+i);for (long i=1;i<N2+1;i++)scanf("%ld",num2+i);long ans = 0;for (long i=1;i<N1+1;i++){for (long j=1;j<N2+1;j++){for (long k=0;k<2;k++){if ( k == 1 ){for (long p=1;p<i;p++)for (long q=1;q<j;q++)f[i][j][k] = MAX(f[i][j][k],f[p][q][k^1]);}else{if (num1[i] == num2[j]) continue;for (long p=1;p<i;p++)for (long q=1;q<j;q++)if (num1[p] == num2[j]&&num2[q] == num1[i])f[i][j][k] = MAX(f[i][j][k],f[p][q][k^1]+2);}ans = MAX(ans,f[i][j][k]);}}} printf("%ld\n",ans);}return 0;}
优化到O(N^3),最慢的程序。预处理优化,预处理出数字为(num[i],num[j])的二元组(i,j)。枚举空间减少了很多。但是也许因为multimap本身效率低下的原因吧。等会儿看我改成二维数组。还有我的方程本来就不好,因此无法突破障碍吧。
一开始忘了初始化hash,还有忘记了判断取出来的是不是x<i且y<j。。主要就是类似于map这之类的长得不像数组的广义数组,一定要记得该初始化的地方要初始化
#include <cstdio>#include <map>#include <algorithm>#define MAX(a,b) ((a)>(b)?(a):(b))#define MIN(a,b) ((a)<(b)?(a):(b))long num1[110];long num2[110];long f[110][110][110];struct Pair{long x;long y;Pair(long xx,long yy):x(xx),y(yy){}bool operator<(const Pair& p2)const{if(x==p2.x)return y<p2.y;return x<p2.x;}Pair(){}};using std::make_pair;using std::multimap;multimap<Pair,Pair> hash;multimap<Pair,Pair>::iterator it1;int main(){freopen("cm.in","r",stdin);freopen("cm.out","w",stdout);long M;scanf("%ld",&M);while (M--){long N1;long N2;scanf("%ld%ld",&N1,&N2);for (long i=1;i<N1+1;i++)for (long j=1;j<N2+1;j++)for (long k=0;k<2;k++)f[i][j][k] = 0;for (long i=1;i<N1+1;i++)scanf("%ld",num1+i);for (long i=1;i<N2+1;i++)scanf("%ld",num2+i);hash.clear();for (long i=1;i<N1+1;i++)for (long j=1;j<N2+1;j++)if (num1[i]-num2[j])hash.insert(make_pair(Pair(num1[i],num2[j]),Pair(i,j)));long ans = 0;Pair pos;for (long i=1;i<N1+1;i++){for (long j=1;j<N2+1;j++){for (long k=0;k<2;k++){if ( k == 1 ){for (long p=1;p<i;p++)for (long q=1;q<j;q++)f[i][j][k] = MAX(f[i][j][k],f[p][q][k^1]);}else{it1 = hash.find(Pair(num2[j],num1[i]));while (it1 != hash.end() && it1->first.x == num2[j]&& it1->first.y == num1[i]){if (it1->second.x < i && it1->second.y < j){pos = it1->second;f[i][j][k] = MAX(f[i][j][k],f[pos.x][pos.y][k^1]+2);}it1 ++;}}ans = MAX(ans,f[i][j][k]);}}} printf("%ld\n",ans);}return 0;}
把上面那个改成二维数组了。Pair hash[101][101][801]是自己大概估计的,不敢大了,会爆空间。。。改了半天,速度终于和朴素一样了。。。
#include <cstdio>#define MAX(a,b) ((a)>(b)?(a):(b))#define MIN(a,b) ((a)<(b)?(a):(b))long num1[110];long num2[110];long f[101][101][101];struct Pair{long x;long y;};Pair hash[101][101][801];long cnt[110][110];int main(){freopen("cm.in","r",stdin);freopen("cm.out","w",stdout);long M;scanf("%ld",&M);long N1=0;long N2=0;while (M--){for (long i=1;i<N1+1;i++)for (long j=1;j<N2+1;j++){cnt[num1[i]][num2[j]] = 0;for (long k=0;k<2;k++)f[i][j][k] = 0;}scanf("%ld%ld",&N1,&N2); for (long i=1;i<N1+1;i++)scanf("%ld",num1+i);for (long i=1;i<N2+1;i++)scanf("%ld",num2+i);for (long i=1;i<N1+1;i++)for (long j=1;j<N2+1;j++)if (num1[i]-num2[j]){hash[num1[i]][num2[j]][++cnt[num1[i]][num2[j]]].x = i;hash[num1[i]][num2[j]][cnt[num1[i]][num2[j]]].y = j;}long ans = 0;for (long i=1;i<N1+1;i++){for (long j=1;j<N2+1;j++){for (long k=0;k<2;k++){if ( k == 1 ){for (long p=1;p<i;p++)for (long q=1;q<j;q++)f[i][j][k] = MAX(f[i][j][k],f[p][q][k^1]);}else{for (long l=1;l<cnt[num2[j]][num1[i]]+1;l++){long x = hash[num2[j]][num1[i]][l].x;long y = hash[num2[j]][num1[i]][l].y;if (x<i && y<j)f[i][j][k] = MAX(f[i][j][k],f[x][y][k^1]+2);}}ans = MAX(ans,f[i][j][k]);}}} printf("%ld\n",ans);}return 0;}
- 【动态规划】Crossed Matchings
- poj 1692 Crossed Matchings 动态规划
- poj 1692 Crossed Matchings 动态规划
- ZOJ 1425 Crossed Matchings(动态规划)
- Crossed Matchings——动态规划
- 北大ACM poj1692 Crossed Matchings(动态规划)
- POJ1692————Crossed Matchings(动态规划)
- PKU1692 Crossed Matchings
- POJ 1692 Crossed Matchings
- pku1692 Crossed Matchings
- ZOJ1425 POJ1692 Crossed Matchings
- poj 1692 Crossed Matchings
- ZOJ1425 Crossed Matchings dp
- zoj 1425 Crossed Matchings
- POJ1692:Crossed Matchings
- Crossed Matchings zoj1425 dp
- POJ 1692 Crossed Matchings
- POJ1692 Crossed Matchings
- 给Button/input添加链接,前进,后退等功能
- 缓冲执行动作
- struts2 之 访问Servlet API
- Ubuntu 10.04小企鹅输入法安装
- 浅谈技术工程师的进步
- 【动态规划】Crossed Matchings
- 杭电hdu 2079 选课时间(题目已修改,注意读题) 母函数
- hdoj1217
- Struts2标签嵌套问题
- 2001年蒲慕明教授写给他实验室学生的信
- poj2750 线段树+动态规划
- 2
- 域名解析文件hosts文件是什么?如何修改hosts文件?
- STL