程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> nyoj 61 傳紙條,nyoj 712 探尋寶藏 雙進程dp

nyoj 61 傳紙條,nyoj 712 探尋寶藏 雙進程dp

編輯:C++入門知識

題目大意是一個機器人從1.1出發,要到達m.n點,去的時候只能往右或往上走,回來的時候只能往上或往左走,但是一個點只能走一次,沿途每個點均有寶藏,問最多能拿回寶物的價值是多少。

此問題等價於從1.1出發兩個機器人,均要到達m.n點,設兩個機器人的速度是一定的,則每一個時刻兩個機器人均不能走到相同的格子內,(除了到達m.n的時候)。

若想去的兩個機器人不走到同一點,則只需要任意時刻,機器人1所在的行數不等於機器人2所在的行數。因為速度相同,出發點相同,若某一時刻k時兩個機器人到達了同一行,則他們的列數也必然會相同,所以只需要不在同一行即可,

設f[k][i][j]為第k步時1號機器人在i行2號機器人走到j行所收集的最大寶物價值,則f[k][i][j]=max(f[k-1][i-1][j],f[k-1][i][j-1],f[k-1][i][j],f[k-1][i-1][j-1])+a[i][k+2-i]+a[j][k+2-j];

如果設1號機器人走的是左邊的路線,2號機器人走的是右邊的路線,由於路線不想交,所以1號機器人第一步是往下的,而2號機器人是往右的,而到達終點前1號機器人不會達到第n列,同樣2號機器人不會到達第m行,然後i和j的取值范圍要考慮,必須使得兩個的行數均在(1,m)之間,列數均在(1,n)之間,而如果k+1<m時,行數均是小於m的,

我們同樣可以這樣考慮,由於機器人每前進一步,行數和列數有且僅有一個將增加1,所以我們可以考慮k的值代表行數和列數的和,則樣比較容易理解,由於到達終點的時候,兩條線路必須相交,所以我們可以不讓到達終點,即k<m+n;狀態轉移方程就變成了f[k][i][j]=max(f[k-1][i-1][j],f[k-1][i][j-1],f[k-1][i][j],f[k-1][i-1][j-1])+a[i][k-i]+a[j][k-j];(k>=3&&k<m+n);

 


參考代碼如下;


[cpp]
#include <iostream>  
#include <cstring>  
#define MAX_SIZE 51  
using namespace std; 
int f[2*MAX_SIZE+10][MAX_SIZE+10][MAX_SIZE+10]; 
int a[MAX_SIZE+10][MAX_SIZE+10]; 
int m,n; 
int max(int a,int b) 

    if(a>b) 
        return a; 
    return b; 

void execute() 

    if(m==1||n==1) 
    { 
        cout<<0<<endl; 
        return ; 
    } 
    memset(f,0x80,sizeof(f)); 
    int k,i,j; 
    f[2][1][1]=0; 
    for(k=3;k<m+n;k++) 
    { 
        for(i=2;i<k&&i<=m;i++) 
        { 
            if(k-i>=n||k-i<1) 
                continue; 
            for(j=1;j<k-1&&j<=m-1;j++) 
            { 
                if(i==j) 
                    continue; 
                if(k-j>n||k-j<=1) 
                    continue; 
                f[k][i][j]=max(max(f[k-1][i-1][j],f[k-1][i-1][j-1]),max(f[k-1][i][j-1],f[k-1][i][j])); 
                f[k][i][j]=f[k][i][j]+a[i][k-i]+a[j][k-j]; 
            } 
        } 
    } 
    int ans=f[m+n-1][m][m-1]+a[m][n]; 
    cout<<ans<<endl; 
 

int main() 

    int T; 
    cin>>T; 
    while(T--) 
    { 
        cin>>m>>n; 
        for(int i=1;i<=m;i++) 
            for(int j=1;j<=n;j++) 
                cin>>a[i][j]; 
        execute(); 
    } 
    return 0; 

#include <iostream>
#include <cstring>
#define MAX_SIZE 51
using namespace std;
int f[2*MAX_SIZE+10][MAX_SIZE+10][MAX_SIZE+10];
int a[MAX_SIZE+10][MAX_SIZE+10];
int m,n;
int max(int a,int b)
{
 if(a>b)
  return a;
 return b;
}
void execute()
{
 if(m==1||n==1)
 {
  cout<<0<<endl;
  return ;
 }
 memset(f,0x80,sizeof(f));
 int k,i,j;
 f[2][1][1]=0;
 for(k=3;k<m+n;k++)
 {
  for(i=2;i<k&&i<=m;i++)
  {
   if(k-i>=n||k-i<1)
    continue;
   for(j=1;j<k-1&&j<=m-1;j++)
   {
    if(i==j)
     continue;
    if(k-j>n||k-j<=1)
     continue;
    f[k][i][j]=max(max(f[k-1][i-1][j],f[k-1][i-1][j-1]),max(f[k-1][i][j-1],f[k-1][i][j]));
    f[k][i][j]=f[k][i][j]+a[i][k-i]+a[j][k-j];
   }
  }
 }
 int ans=f[m+n-1][m][m-1]+a[m][n];
 cout<<ans<<endl;

}
int main()
{
 int T;
 cin>>T;
 while(T--)
 {
  cin>>m>>n;
  for(int i=1;i<=m;i++)
   for(int j=1;j<=n;j++)
    cin>>a[i][j];
  execute();
 }
 return 0;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved