您的位置:首页 > 其它

UVA DP入门专题(二)最长公共子序列 打印方法

2012-05-05 10:17 435 查看
10285 - Longest Run on a Snowboard491055.11%203693.76%
1007594310285Longest Run on a SnowboardAcceptedC++0.0242012-05-05 02:12:46
滑雪, 变相的最长递减子序列,它不是求一行的最长递增子序列,而是求在一个方阵,可以往上下左右四个方向走的最长递减路线。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
 
int max(int a,int b){return a>b?a:b;}
int map[105][105],dp[105][105];
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};

class CPoint{
public:
	int height;
	int x;
	int y;
	friend bool operator < (const CPoint &a,const CPoint &b){
		return a.height < b.height;
	}
}road[10005];

int main(int i, int j)
{
//	freopen("input.txt","r",stdin);
	char name[100];
	int N,R,C;
	scanf("%d",&N);

	while(N--){
		scanf("%s %d %d",name,&R,&C);
		int numRoad=0;
	
		for(i=0; i<R; ++i){
			for(j=0; j<C; ++j){
				scanf("%d",&map[i][j]);
				road[numRoad].height=map[i][j];
				road[numRoad].x=i;
				road[numRoad].y=j;
				++numRoad;
			}
		}
		
		sort(road,road+numRoad);
	//	memset(dp,1,sizeof(dp));   /* 不能用这个,无法初始化为1 */
		for(i=0; i<R; ++i){
			for(j=0; j<C; ++j)
			 dp[i][j]=1;
		}
 
		int maxRoad = 0;

		for(i=0; i<numRoad; ++i){
			for(j=0; j<4; ++j){
				int dx=road[i].x+dir[j][0];
				int dy=road[i].y+dir[j][1];
				if(dx>=0 && dx<R && dy>=0 && dy<C && map[dx][dy]>map[road[i].x][road[i].y] && dp[road[i].x][road[i].y]+1>dp[dx][dy]){
					dp[dx][dy] = dp[road[i].x][road[i].y]+1;
					if(dp[dx][dy]>maxRoad) maxRoad = dp[dx][dy];
				}
			}
		}
		printf("%s: %d\n",name,maxRoad);  
	}
	return 0;
}
531 - Compromise1093725.82%297069.73%
10076491531CompromiseAcceptedC++0.0322012-05-05 06:18:21
10076471531CompromiseWrong answerC++0.0082012-05-05 06:09:26
10076428531CompromiseWrong answerC++0.0122012-05-05 05:55:44
10076234531CompromiseWrong answerC++0.0322012-05-05 04:32:16
10076222531CompromiseWrong answerC++0.0122012-05-05 04:23:57
10076212531CompromiseCompilation errorC++0.0002012-05-05 04:22:35
这题WA了多次,原因在于不懂的打印出 最长公共子序列。 网上查了下,学习了两种打印方式:最长公共子序列问题,打印路径总结了两个方法,一个是递归指向,就像前面做的01背包问题如:
for(int i = 1; i < n; i ++)
        for(int j = 0; j < n-i; j ++)
            for(int k = j; k < i+j; k ++)
            {
                if(k == j) 
                {
                    f[j][i+j] = f[j][k]+f[k+1][i+j]+A[j][0]*A[k][1]*A[i+j][1];
                    part1[j][i+j] = k;//赋值
                }
                if(f[j][k]+f[k+1][i+j]+A[j][0]*A[k][1]*A[j+i][1] < f[j][i+j]) 
                    {
                        f[j][i+j] = f[j][k]+f[k+1][i+j]+A[j][0]*A[k][1]*A[j+i][1];
                        part1[j][i+j] = k;//赋值
                    }
            }
void printpath(int a, int b)//输出
{
    if(a == b)
    {
        printf("A%d", a + 1);
        return ;
    }
    printf("(");
    printpath(a, part1[a]);
    printf(" x ");
    printpath(part1[a][b] + 1, b);
    printf(")");
}
例如:
for(int i = 1; i <= cdnum; i ++)
        for(int j = 0; j <= tap; j ++)
        {
            f[i][j] = f[i-1][j];
            p[i][j] = j;//赋值
            if(j>=num[i]&&f[i-1][j-num[i]]+num[i] > f[i][j])
            {
                f[i][j] = f[i-1][j-num[i]]+num[i]; p[i][j] = j-num[i];//赋值
            }
        }
void print(int i, int j)//打印路径
{
    if(i == 0)
        return;
    print(i - 1, p[i][j]);
    if(p[i][j] < j)
        printf("%d ", num[i]);
}
这第二种就是今天用到的 赋值遍历打印路径;
for(int i = 1; i <= m; i ++)
        for(int j = 1; j <= n; j ++)
            if(!strcmp(a[i], b[j])) 
                {
                    f[i][j] = f[i-1][j-1] + 1;
                    p[i][j] = 1;//赋值
                }
            else if(f[i-1][j]>f[i][j-1])
                        {
                            f[i][j] = f[i-1][j];
                            p[i][j] = 0;//赋值
                        }
                        else 
                        {
                            f[i][j] = f[i][j-1];
                            p[i][j] = -1;//赋值
                        }
void print(int i , int j)//输出{    if(!i || !j)        return ;    if(p[i][j] == 1)    {        print(i-1,j-1);        if(flag)      printf(" ");    else      flag = 1;    printf("%s", a[i]);    }    else if(p[i][j] == 0)                print(i-1,j);                else print(i,j-1);}
/*UVa 531	Compromise最长公共子序列打印  */#include<iostream>#include<string>#include<cstring>#include<cstdio>using namespace std;string text1[105],text2[105];int dp[105][105],p[105][105];bool flag;void print(int i,int j){	if(!i || !j)		return ;	if(p[i][j]==1){		print(i-1,j-1);		if(flag)			cout<<" ";		else			flag=true;		cout << text1[i];	}	else if(p[i][j]==0){		print(i-1,j);	}	else		print(i,j-1);}int main(int i,int j){  	freopen("input.txt","r",stdin);	 	int len1,len2;	while(cin>>text1[1]){		len1 = 2;		len2 = 1;		while(cin >> text1[len1]){			if(text1[len1]=="#") break;			++len1;		}		while(cin >> text2[len2]){			if(text2[len2]=="#") break;			++len2;		}		--len1; --len2;		memset(dp,0,sizeof(dp)); 		for(i=1; i<=len1; ++i){			for(j=1; j<=len2; ++j){				if(text1[i]==text2[j]){					dp[i][j] = dp[i-1][j-1]+1;					p[i][j] = 1;				}				else{					if(dp[i-1][j]>dp[i][j-1]){						dp[i][j] = dp[i-1][j];						p[i][j] = 0;					}					else{						dp[i][j] = dp[i][j-1];								p[i][j] = -1;					}				}			}		}		flag=false;		print(len1,len2);		printf("\n");	}	return 0;}
624 - CD (01背包打印路径)
#include<cstdio>#include<cstring>#define MAXN 10000int track[MAXN];int dp[22][MAXN];int path[22][MAXN];int max(int a,int b){return a>b?a:b;}void print(int i, int j)//打印路径{    if(i == 0)        return;    print(i-1, path[i][j]);    if(path[i][j] < j)        printf("%d ",track[i]);}int main(){	//freopen("input.txt","r",stdin);	int N,t,i,j;	while(scanf("%d %d",&N,&t)!=EOF){		for(i=1; i<=t; ++i)			scanf("%d",&track[i]);		memset(dp,0,sizeof(dp));		memset(path,0,sizeof(path));		for(i=1; i<=t; ++i){			for(j=0; j<=N; ++j){				dp[i][j] = dp[i-1][j];				path[i][j] = j;				if(j>=track[i]&&dp[i-1][j-track[i]]+track[i]>dp[i][j]					&&dp[i-1][j-track[i]]+track[i]<=N){					dp[i][j]=dp[i-1][j-track[i]]+track[i];					path[i][j]=j-track[i];				}			}		}		print(t,N);	 	printf("sum:%d\n",dp[t]);	}		return 0;}
[b]—— 生命的意义,在于赋予它意义。
原创 http://blog.csdn.net/shuangde800 , By D_Double
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: