zoukankan      html  css  js  c++  java
  • NYOJ 16 矩形嵌套(经典动态规划)

    传送门

    Description

    有n个矩形,每个矩形可以用a,b来描述,表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度)。例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中。你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内。

    Input

    第一行是一个正正数N(0<N<10),表示测试数据组数,
    每组测试数据的第一行是一个正正数n,表示该组测试数据中含有矩形的个数(n<=1000)
    随后的n行,每行有两个数a,b(0<a,b<100),表示矩形的长和宽

    Output

    每组测试数据都输出一个数,表示最多符合条件的矩形数目,每组输出占一行

    Sample Input

    1
    10
    1 2
    2 4
    5 8
    6 10
    7 9
    3 1
    5 8
    12 10
    9 7
    2 2

    Sample Output

    5

    思路

      一、对于输入的a,b将较大的值赋给矩形的长,较小的值赋给矩形的宽,然后对矩形的长从小到大排序,这样保证了前面的矩阵不可能嵌套在后面中,然后只要对宽进行判断就行了。这样问题就转化为最长上升子序列了。

      二、利用图模型解决,假设X可以嵌套在Y中,就从X到Y连一条边,这个有向图是无环的,也就是DAG图,这样,问题转化为求DAG上的最长路径

     

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn = 1005;
    struct Node{
    	int len,wid;
    }node[maxn];
    
    bool cmp(struct Node xx,struct Node yy)
    {
    	if (xx.len == yy.len)	return xx.wid < yy.wid;
    	else	return xx.len < yy.len;
    }
    
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while (T--)
    	{
    		int N,l,w,res = 0;
    		int dp[maxn] = {0};
    		scanf("%d",&N);
    		for (int i = 0;i < N;i++)
    		{
    			scanf("%d%d",&l,&w);
    			node[i].len = l > w?l:w;
    			node[i].wid = w < l?w:l;
    		}
    		sort(node,node+N,cmp);
    		for (int i = 0;i < N;i++)     //转化为求最长上升子序列 
    		{
    			dp[i] = 1;
    			for (int j = 0;j < i;j++)
    			{
    				if (node[i].wid > node[j].wid && node[i].len > node[j].len && dp[j] + 1 > dp[i])
    				{
    					dp[i] = dp[j] + 1;
    				}
    			}
    			res = max(res,dp[i]);
    		}
    		printf("%d
    ",res);	
    	}
    	return 0;
    }
    

      

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn = 1005;
    struct Node{
    	int len,wid;
    }node[maxn];
    int dp[maxn],edge[maxn][maxn];
    
    bool cmp(struct Node x,struct Node y)
    {
    	if (x.len == y.len)	return x.wid < y.wid;
    	else	return x.len < y.len;
    } 
    
    void addedge(int N)
    {
    	for (int i = 0;i < N;i++)
    	{
    		for (int j = i + 1;j < N;j++)
    		{
    			if (node[i].len < node[j].len && node[i].wid < node[j].wid)	edge[i][j] = 1;
    		}
    	}
    }
    
    int solve(int i,int N)
    {
    	int &ans = dp[i];          //为表项dp[i]声明了一个引用,这样,任何对ans的读写实际上都是在对dp[i]进行,实际上,当dp[i]换成dp[i][j][k]这样的长名字,该技巧优势更明显
    	if (ans > 0)	return ans;
    	ans = 1;
    	for (int j = 0;j < N;j++)	if (edge[i][j])	ans = max(ans,solve(j,N) + 1);
    	return ans;
    }
    
    int main()
    {
    	int T,N,x,y;
    	scanf("%d",&T);
    	while (T--)
    	{
    		int tmp,res = 0;
    		memset(dp,0,sizeof(dp));
    		memset(edge,0,sizeof(edge));
    		scanf("%d",&N);
    		for (int i = 0;i < N;i++)
    		{
    			scanf("%d%d",&x,&y);
    			node[i].len = x>y?x:y;
    			node[i].wid = x<y?x:y;
    		}
    		sort(node,node+N,cmp);
    		addedge(N);
    		for (int i = 0;i < N;i++)
    		{
    			tmp = solve(i,N);
    			res = tmp>res?tmp:res;
    		}
    		printf("%d
    ",res);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Write an algorithm such that if an element in an MxN matrix is 0, its entire row and column is set to 0.
    旋转二维数组
    replace empty char with new string,unsafe method和native implementation的性能比较
    判断一字符串是否可以另一字符串重新排列而成
    移除重复字符的几个算法简单比较
    也来纠结一下字符串翻转
    判断重复字符存在:更有意义一点
    程序员常去网站汇总
    sublime
    针对程序集 'SqlServerTime' 的 ALTER ASSEMBLY 失败,因为程序集 'SqlServerTime' 未获授权(PERMISSION_SET = EXTERNAL_ACCESS)
  • 原文地址:https://www.cnblogs.com/ZhaoxiCheung/p/5876685.html
Copyright © 2011-2022 走看看