滑雪, 变相的最长递减子序列,它不是求一行的最长递增子序列,而是求在一个方阵,可以往上下左右四个方向走的最长递减路线。
#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;
}
这题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][b]);
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 10000
int 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][N]);
}
return 0;
}
—— 生命的意义,在于赋予它意义。
分享到:
相关推荐
uva531最长公共子序列问题水题,应用简单的dp即可ac有更快速的方法欢迎讨论
算法竞赛入门经典(第二版)的习题都是UVa上的, 但是UVa太慢了太慢了太慢了太慢了太慢了, 于是我把各章习题的pdf一次性打包下载到本地, 和大家分享:)
这不是原书pdf,找算法竞赛入门经典(第二版)pdf的同学请不要下了。 这个是书里采用的习题和例题的UVa原题pdf(英文)。 分享这个文件的原因是国内上UVa太慢了,有时候UVa还会挂。 而且书里把输入输出样例省去了,...
《算法竞赛入门经典》UVa配套题目pdf版完整
收集了刘汝佳的算法竞赛入门经典这本书的所有在uva上的课后习题,按照章节分类,全部为pdf格式
其实刚刚就从下载频道下了一个名为 “算法入门经典UVa配套题目pdf”的文件,也是题目PDF,不过缺少Volume 0 以及Volume 3多了一个压缩包,所以自己整理了一下,收录了Volume 0 现在有上传一遍,希望福泽后人~
UVA109的题解,经测试完全正确,还附有题解。
uva272
python从入门到精通视频将复杂的编程概念分解成简单的步骤,简单易懂。作者通过多年的教学经验精心挑选出了最有特点的例子,手把手地实例教学。学习更加轻松。以一学就会的理念讲授Python是什么,需要哪些软件,相...
包含UVA在线OJ系统的绝大部分的示例代码,并都已AC,可在刷题时参考
有uva刘汝佳文件夹的50道题解,从数据结构开始,以后慢慢上传
算法竞赛入门经典(第二版)习题的原题PDF,UVa上都有,整合到一起。
uva最全ac代码
UVa在我看来是比较全的一个题解,希望能帮助大家。欢迎下载。
uva10755 ac 代码,可以随意更改下载
uva357的栈实现版本
UVA 题目,不是很难,试试吧
世界著名大学UVA OJ平台上的题目部分分类,分的不好请原谅。
1.Uva_base的编译 在编译球队时,则需要在当前球队文件夹下打开终端输入执行以下命令(以下命令都是在root下执行的): ./configure make clean make 如果运行Uva_base后,出现球员越界或掉线的情况,就重新...
uva_trilearn2002 源代码