第一次做动规题目,下面均为个人理解以及个人方法,状态转移方程以及状态的定义也是依据个人理解。请过路大神不吝赐教。

状态:每一列的每个数[ i ][ j ]都是一个状态;

然后定义状态[ i ][ j ]的指标函数d[ i ][ j ]为从[ i ][ j ]向右出发的能够得到的最小的整数和;

状态转移方程:d[ i ][ j ]=min(d[ i+1 ][ j+1 ][ i-1 ][ j+1 ][ i ][ j+1 ])+a[ i ][ j ];

当中a[ i ][ j ]为当前位置的数值;

然后有了这些就能够用自己熟悉的方式对问题求解了。

我所知道的合理求解过程有两种:记忆化搜索和递推。

我所知道的输出方法有两种:在求解过程中记录最优位置并在最后输出。全然在输出过程中寻求最佳位置并输出;

下面是自己写的两种输出不同的方法,其处理求解过程均为递推,我觉得对本题来讲记忆化搜索比較复杂,而递推又显而易见

1.

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std; typedef long long ll;
int m,n;
int a[50][1100];
int rd[50][1100];
ll d[50][1100]; ll min_ans(ll t1,ll t2 ,ll t3)
{
long long temp=min(t1,t2);
temp=min(temp,t3);
return temp;
}
int min_pos(ll ans,int y,int x1,int x2,int x3)
{
int pos=m+1;
if(ans==d[x1][y])
{
pos=min(pos,x1);
}
if(ans==d[x2][y])
{
pos=min(pos,x2);
}
if(ans==d[x3][y])
{
pos=min(pos,x3);
}
return pos;
}
void dp()
{
for(int i=n;i>=1;i--)
{
for(int j=1;j<=m;j++)
{
int temp1=j-1;
if(temp1==0) temp1=m;
int temp2=j+1;
if(temp2>m) temp2=1;
ll t1,t2,t3,ans;int pos;
t1=d[temp1][i+1];t2=d[j][i+1];t3=d[temp2][i+1];
d[j][i]=min_ans(t1,t2,t3)+a[j][i];
rd[j][i]=min_pos(d[j][i]-a[j][i],i+1,temp1,j,temp2);
}
}
}
void print_ans(int pp)
{
int cur=1;
printf("%d",pp);
while(cur!=n)
{
printf(" %d",rd[pp][cur]);
pp=rd[pp][cur];
cur++;
}
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
memset(d,0,sizeof(d));
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
}
}
dp();
long long min_ = -1;
for(int i=1;i<=m;i++)
{
if(min_==-1) min_=d[i][1];
else
min_=min(min_,d[i][1]);
}
int pp;
for(int i=1;i<=m;i++)
{
if(d[i][1]==min_)
{
pp=i;
break;
}
}
print_ans(pp);
printf("\n");
printf("%lld",d[pp][1]);
printf("\n");
}
return 0;
}

2.

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; typedef long long ll;
int m,n;
int a[50][1100];
int rd[50][1100];
ll d[50][1100]; ll min_ans(ll t1,ll t2 ,ll t3)
{
long long temp=t1>t2? t2:t1;
return temp>t3?t3:temp;
} void dp()
{
for(int i=n; i>=1; i--)
{
for(int j=1; j<=m; j++)
{
int temp1=j-1;
if(temp1==0) temp1=m;
int temp2=j+1;
if(temp2>m) temp2=1;
ll t1,t2,t3,ans;
int pos;
t1=d[temp1][i+1];
t2=d[j][i+1];
t3=d[temp2][i+1];
d[j][i]=min_ans(t1,t2,t3)+a[j][i];
}
}
}
void print_ans(int pp,int cur)
{
printf("%d",pp);
cur++;
while(1&&cur<=n)
{
int i;
for(i=1; i<=m; i++)
{
if((d[i][cur]==d[pp][cur-1]-a[pp][cur-1]))
{
if(pp==1&&(i==m||i==pp||i==pp+1))
{
printf(" %d",i);
break;
}
else if(pp==m&&(i==1||i==pp||i==pp-1))
{
printf(" %d",i);
break;
}
else if(i>=pp-1&&i<=pp+1)
{
{
printf(" %d",i);
break;
}
}
else
continue;
}
}
pp=i;
cur++;
if(cur>n)
break;
}
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
memset(d,0,sizeof(d));
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&a[i][j]);
}
}
dp();
long long min_ = -1;
for(int i=1; i<=m; i++)
{
if(min_==-1) min_=d[i][1];
else
min_=min(min_,d[i][1]);
}
int pp;
for(int i=1; i<=m; i++)
{
if(d[i][1]==min_)
{
pp=i;
break;
}
}
print_ans(pp,1);
printf("\n");
printf("%I64d",d[pp][1]);
printf("\n");
}
return 0;
}

第一次做动规题目,花了好久才做好,由于期间出了一些小错误(如今看来依然是一些细节上的错误。与动规无关),并且由于对动规的不熟悉。心里对其也有一点点的恐惧。

可是认定这一道动规并不难,有时自己独立杰出的第一道动规题目。十分想要独立将其AC。然后一直找细节測数据。最终是找到了几处非常不应该犯的细节处理上的错误。这一点让我非常伤心。但最终的AC胜过千言万语。

之后选择还有一种方法,也是磕磕绊绊才写出AC代码orz...

这就算是开了动规吧,多思考多钻研,多学习别人的优秀思路

uva 116 - Unidirectional TSP (动态规划)的更多相关文章

  1. uva 116 Unidirectional TSP (DP)

    uva 116 Unidirectional TSP Background Problems that require minimum paths through some domain appear ...

  2. uva 116 Unidirectional TSP【号码塔+打印路径】

    主题: uva 116 Unidirectional TSP 意甲冠军:给定一个矩阵,当前格儿童值三个方向回格最小值和当前的和,就第一列的最小值并打印路径(同样则去字典序最小的). 分析:刚開始想错了 ...

  3. UVA 116 Unidirectional TSP(dp + 数塔问题)

     Unidirectional TSP  Background Problems that require minimum paths through some domain appear in ma ...

  4. UVA 116 Unidirectional TSP(DP最短路字典序)

    Description    Unidirectional TSP  Background Problems that require minimum paths through some domai ...

  5. uva 116 Unidirectional TSP(动态规划,多段图上的最短路)

    这道题目并不是很难理解,题目大意就是求从第一列到最后一列的一个字典序最小的最短路,要求不仅输出最短路长度,还要输出字典序最小的路径. 这道题可以利用动态规划求解.状态定义为: cost[i][j] = ...

  6. UVa - 116 - Unidirectional TSP

    Background Problems that require minimum paths through some domain appear in many different areas of ...

  7. UVA - 116 Unidirectional TSP 多段图的最短路 dp

    题意 略 分析 因为字典序最小,所以从后面的列递推,每次对上一列的三个方向的行排序就能确保,数字之和最小DP就完事了 代码 因为有个地方数组名next和里面本身的某个东西冲突了,所以编译错了,后来改成 ...

  8. UVA 116 Unidirectional TSP 经典dp题

    题意:找最短路,知道三种行走方式,给出图,求出一条从左边到右边的最短路,且字典序最小. 用dp记忆化搜索的思想来考虑是思路很清晰的,但是困难在如何求出字典序最小的路. 因为左边到右边的字典序最小就必须 ...

  9. UVa 116 Unidirectional TSP (DP)

    该题是<算法竞赛入门经典(第二版)>的一道例题,难度不算大.我先在没看题解的情况下自己做了一遍,虽然最终通过了,思路与书上的也一样.但比书上的代码复杂了很多,可见自己对问题的处理还是有所欠 ...

随机推荐

  1. Android 当修改一些代码时,使用什么编译命令可以最有效率

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处:          CSDN:http://www.csdn.net        ...

  2. Triangular numbers

    http://codeforces.com/problemset/problem/47/A Triangular numbers time limit per test 2 seconds memor ...

  3. C# 使用DateTime.TryParseExact将自定义日期类型转换成日期

    在C#中如果将一个字符串类型的日期转换成日期类型很方便的 即使用Convert.ToDateTime("2015/01/01").ToString()或DateTime.TryPa ...

  4. Windows 8.1 64位版本安装.Net Framework3.5

    最近刚把个人电脑切换成了Win 8.1 64位版本,但在使用某些Ms的某此产品时会提示没有安装.Net Framework3.5,但按照他的提示需要在线安装而且速度很慢,因为之前搞过WinServer ...

  5. POJ 1265:Area

    Area Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4725   Accepted: 2135 Description ...

  6. COM如何区分套间线程(apartment thread)和自由线程(free thread)

     

  7. json树递归js查询json父子节点

    上代码,直接另存为html打开,看console控制台就可以看到效果了 <!DOCTYPE html> <html lang="en"> <head& ...

  8. UE如何去除重复行,删除重复行

    1 如图所示,原理一个文本文档有两千多行,但是有大量的重复 2 使用UE的排序功能,有删除重复行的选项. 3 处理之后只剩下不到两百行了.

  9. hdu4497 GCD and LCM

    GCD and LCM Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others) Total S ...

  10. break的使用方法

    private static void test() {  for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { Syst ...