2012-07-09 28 views
7

有一款有趣的游戏叫做单人游戏。它在m*n网格上播放。每个网格单元格中都有一个非负整数。您从0开始。您无法输入其中包含整数0的单元格。您可以在任何想要的单元格开始和结束游戏(当然,单元格中的数字不能为0)。在每一步中,您都可以上下左右移动到相邻的网格单元。您最后可以得到的分数是您路径上的数字总和。但是最多可以输入一次单元格。
网格步行高分

该游戏的目的是让你的分数尽可能高。

输入:
输入的第一行是整数T测试用例的个数。每个测试用例的第一行是一行,包含两个整数mn,这是网格中的行数和列数。每个下一个的m线包含n空格隔开的整数D指示在对应的小区

输出数:
对于每组测试输出在一行中是可以在最后得到最高得分的整数。

限制条件:
T是小于7
D小于60001.
mn是小于8

样品输入:

4 
1 1 
5911 
1 2 
10832 0 
1 1 
0 
4 1 
0 
8955 
0 
11493 

样品输出:

5911 
10832 
0 
11493 

我尝试过,但我的做法是工作很慢的7×7 grid.I我试图递归访问网格的每一个可能的路径和比较每path.Below的总和是我的代码

#include<iostream> 
#include <algorithm> 
#include <stdio.h> 
using namespace std; 

int max(int a,int b,int c, int d) 
{ 
int max = a; 
if(b>max) 
    max = b; 
if(c>max) 
    max = c; 
if(d>max) 
    max = d; 
return max; 
} 

int Visit_Component(int (*A)[8], int Visit[8][8], int m,int n , int row, int col) 
{ 

if ((row >= m) || (col >= n) || (col < 0) || (row < 0) || A[row][col] == 0   || Visit[row][col] == 1) 
{ 
    return 0; 
} 
else 
{ 

    Visit[row][col] = 1; 
    int a= 0,b=0,c=0,d=0,result =0; 
    a = Visit_Component(A, Visit,m,n, row+1, col); 
    b = Visit_Component(A, Visit,m,n, row, col +1); 
    c = Visit_Component(A, Visit,m,n, row, col -1); 
    d = Visit_Component(A, Visit,m,n, row-1, col); 
    Visit[row][col] = 0; 
    result = A[row][col] + max(a,b,c,d); 
    return result; 
} 
} 

int main(){ 

int T; 
scanf("%d",&T); 
for(int k =0; k<T;k++) 
{ 
    int N ; 
    int M; 
    int count = 0; 
    int maxcount = 0; 
    scanf("%d %d",&M,&N); 
    int C[8][8]; 
    int visit[8][8]; 
    for(int i = 0; i < M; i++) 
     for(int j = 0; j < N; j++) 
     { 
      scanf("%d",&C[i][j]); 
      visit[i][j] = 0; 
     } 
    for(int i= 0 ; i< M ; i++) 
    { 
     for(int j =0; j< N ; j++) 
     { 

      count = Visit_Component(C, visit,M,N, i, j); 
      if(count > maxcount) 
      { 
       maxcount = count; 
      } 
     } 
    } 
    printf("%d\n",maxcount); 
} 
return 0; 
} 

请给我建议如何优化这种方法或更好的算法。

+0

由于代码有效,应该移动到代码审查? – tomdemuyt 2012-07-09 19:10:42

+0

@tomdemuyt代码正在工作,但我正在寻找此代码中的优化,因为它对于大型数据集的工作速度非常慢 – archit 2012-07-09 19:16:28

+0

这不是真正的代码审查,因为问题不在于如何更好地组织代码,而是关于高效算法。 – biziclop 2012-07-09 20:17:13

回答

1

我能想到的一种优化方法是应用Dijkstra's algorithm。该算法将为您提供特定源节点到所有目标节点的最小(在您的情况下为最大)路径。

在这个例子中,第一步是建立一个图。

由于您不知道源节点的起始位置,因此您必须为网格中的每个节点应用Dijkstra算法。时间复杂度会比递归方法更好,因为对于特定的源节点,当找到最大路径时,Dijkstra算法不会经历所有可能的路径。

+1

不幸的是,最长的路径问题是NP完全的,所以Dijkstra(与负负荷周期不存在的假设一起工作)在这里没有帮助。你必须为这个导出一些哈密顿路径搜索启发式。但比OP的版本更有效率。 – unkulunkulu 2012-07-10 06:23:05

+0

问题陈述明确指出每个网格单元中都有非负整数。 – user1168577 2012-07-10 06:29:56

+0

但迪克斯特拉也找到最短的路径,为了使它找到最长,你将不得不否定所有的权重... – unkulunkulu 2012-07-10 06:38:37

2

由于Wikipedia article on Travelling salesman problem暗示,有确切的算法,快速解决这个任务。但很难找到任何。而且他们很可能很复杂。

至于优化OP的方法,有几种可能性。

从简单的微观优化开始比较容易:条件Visit[row][col] == 1满足最高概率,所以它应该优先。

此外,用动态规划优化分支定界算法以避免重复计算是合理的。在多达19个访问单元的情况下,将计算结果存储在简单的哈希表中可将性能提高25%以上(对于某些改进的哈希表,可能会有更多)。下面是修改后的代码片断:

#include<iostream> 
#include <algorithm> 
#include <stdio.h> 
using namespace std; 

int max(int a,int b,int c, int d) 
{ 
    int max = a; 
    if(b>max) 
    max = b; 
    if(c>max) 
    max = c; 
    if(d>max) 
    max = d; 
    return max; 
} 

typedef unsigned long long ull; 
static const int HS = 10000019; 
static const int HL = 20; 
struct HT { 
    ull v; 
    int r; 
    int c; 
}; 
HT ht[HS] = {0}; 

int Visit_Component(
    int (*A)[8], ull& Visit, int m,int n , int row, int col, int x) 
{ 

    if ((Visit & (1ull << (8*row+col))) || (row >= m) || (col >= n) || 
    (col < 0) || (row < 0) || A[row][col] == 0) 
    { 
    return 0; 
    } 
    else 
    { 
    if (x < HL) 
    { 
     HT& h = ht[(Visit+4*row+col)%HS]; 
     if (h.v == Visit && h.r == row && h.c == col) 
     return 0; 
    } 

    Visit |= (1ull << (8*row+col)); 
    int a= 0,b=0,c=0,d=0,result =0; 
    a = Visit_Component(A, Visit,m,n, row+1, col, x+1); 
    b = Visit_Component(A, Visit,m,n, row, col +1, x+1); 
    c = Visit_Component(A, Visit,m,n, row, col -1, x+1); 
    d = Visit_Component(A, Visit,m,n, row-1, col , x+1); 
    Visit &= ~(1ull << (8*row+col)); 
    result = A[row][col] + max(a,b,c,d); 

    if (x < HL) 
    { 
     HT& h = ht[(Visit+4*row+col)%HS]; 
     h.v = Visit; 
     h.r = row; 
     h.c = col; 
    } 

    return result; 
    } 
} 

int main(){ 

    int T; 
    scanf("%d",&T); 
    for(int k =0; k<T;k++) 
    { 
    int N ; 
    int M; 
    int count = 0; 
    int maxcount = 0; 
    scanf("%d %d",&M,&N); 
    int C[8][8]; 
    ull visit = 0; 
    for(int i = 0; i < M; i++) 
     for(int j = 0; j < N; j++) 
     { 
      scanf("%d",&C[i][j]); 
     } 
    for(int i= 0 ; i< M ; i++) 
    { 
     for(int j =0; j< N ; j++) 
     { 

      count = Visit_Component(C, visit,M,N, i, j, 0); 
      if(count > maxcount) 
      { 
       maxcount = count; 
      } 
     } 
    } 
    printf("%d\n",maxcount); 
    } 
    return 0; 
} 

还有更多的改进可以通过预先处理所述输入矩阵来完成。如果矩阵中没有零或者角落中只有一个零,则可以对所有值进行求和。

如果只有一个零值(不在角落),最多一个非零值应该从总和中排除。如果您发明了一种算法,该算法确定单元的子集,则必须从中删除其中一个单元,您可以从该子集中选择最小值。

如果有两个或更多个零值,使用分支定界算法:在这种情况下,它大约快20倍,因为输入矩阵中的每个零值意味着大约增加五倍的速度。

0
#include<iostream> 
#include<vector> 

using namespace std; 
vector<vector<int> >A; 
vector<vector<bool> >test; 
vector<vector<bool> >test1; 
int sum_max=0; 
int m,n; 
vector<vector<bool> > stamp; 
void color1(int i,int j,vector<vector<bool> >temp_vector,vector<vector<bool> > st,int summ){ 

    temp_vector[i][j]=false;summ+=A[i][j];st[i][j]=true; 
//1.1 
    if(i+1<m && temp_vector[i+1][j]){ 
    if(test1[i+1][j]){ 
        if(sum_max<(summ)){sum_max=summ;stamp=st;} 
        }  
else{color1(i+1,j,temp_vector,st,summ);} 
} 
    //1.2 
    if(i+1<m){if(!temp_vector[i+1][j]){ if(sum_max<(summ)){sum_max=summ;}}} 
    if(i+1>=m){if(sum_max<(summ)){sum_max=summ;}} 

    //2 
if(i-1>=0 && temp_vector[i-1][j]){ 
      if(test1[i-1][j]){ 
        if(sum_max<(summ)){sum_max=summ;} 
        }  
    else{ color1(i-1,j,temp_vector,st,summ);} 
    } 
    //2.2 
    if(i-1>=0){if(!temp_vector[i-1][j]){ if(sum_max<(summ)){sum_max=summ;}}} 
     if(i-1<0){if(sum_max<(summ)){sum_max=summ;}} 

    //3 
    if(j+1<n && temp_vector[i][j+1]){ 
     if(test1[i][j+1]){ 
         if(sum_max<(summ)){sum_max=summ;} 
        }  
    else{  color1(i,j+1,temp_vector,st,summ);}} 
    //3.2 
    if(j+1<n){if(!temp_vector[i][j+1]){ if(sum_max<(summ)){sum_max=summ;}}} 
     if(j+1>=n){if(sum_max<(summ)){sum_max=summ;}} 

    //4 
    if(j-1>=0 && temp_vector[i][j-1]){ 
     if(test1[i][j-1]){ 
        if(sum_max<(summ)){sum_max=summ;} 
        }  
else{  color1(i,j-1,temp_vector,st,summ);}} 
//4.2 
    if(j-1>=0){if(!temp_vector[i][j-1]){ if(sum_max<(summ)){sum_max=summ;}}} 
     if(j+1<0){if(sum_max<(summ)){sum_max=summ;}} 

} 


void color(int i,int j){ 
    test[i][j]=false; 
    if(i+1<m && test[i+1][j]){ 
    color(i+1,j);} 
    if(i-1>=0 && test[i-1][j]){ 
      color(i-1,j); 
} 
if(j+1<n && test[i][j+1]){ 
      color(i,j+1);} 
if(j-1>=0 && test[i][j-1]){color(i,j-1);} 

} 

int main(){ 
    int tc;cin>>tc; 
    for(int i=0;i<tc;i++){ 
     int mp,np; 
     cin>>mp; 
     cin>>np;m=mp;n=np;A.resize(m);test.resize(m);test1.resize(m);int sum=0; 
     vector<bool> ha1(m,1); 
     vector<bool> ha2(n,1); 
     for(int i=0;i<m;i++){A[i].resize(n);test[i].resize(n);test1[i].resize(n); 
       for(int j=0;j<n;j++){ 
         cin>>A[i][j];sum+=A[i][j]; 
                test[i][j]=true;test1[i][j]=false; 
                if(A[i][j]==0){test[i][j]=false;ha1[i]=false;ha2[j]=false;} 
         } 
       }cout<<endl; 
       for(int i=0;i<m;i++){cout<<" "<<ha1[i];} cout<<endl; 
       for(int i=0;i<n;i++){cout<<" "<<ha2[i];} cout<<endl; 
       cout<<"sum "<<sum<<"\n"; 
       int temp_sum=0; 
       for(int i=0;i<m;i++){ 
           for(int j=0;j<n;j++){//if(A[i][j]<=8845){cout<<"\nk "<<A[i][j]<<" "<<(8845-A[i][j]);} 
             if(test[i][j]){ 
                 if((i-1)>=0 && test[i-1][j] && (i+1)<m && test[i+1][j] && (j-1)>=0 && test[i][j-1] && (j+1)<n && test[i][j+1] && test[i-1][j-1] && test[i-1][j+1]&& test[i+1][j-1] && test[i+1][j+1]){ 
                    temp_sum+=A[i][j];test1[i][j]=true;} 

                 } 
                // cout<<test1[i][j]<<" "; 
             }//cout<<"\n"; 
             } 

//   /* 
       for(int i=0;i<m;i++){ 
           for(int j=0;j<n;j++){ 

             if(test1[i][j]){if(!((test1[i-1][j]||test1[i+1][j]) && (test1[i][j-1]||test1[i][j+1]))){ 
                         temp_sum-=A[i][j]; test1[i][j]=false;} 
             } 

                 // 
                // cout<<test1[i][j]<<" "; 
             }// 
             // cout<<"\n"; 
             } 
    //    */ 

       //cout<<"\n temp_sum is "<<temp_sum<<endl; 
       vector<vector<bool> > st(m,vector<bool>(n,0));st=test1; 
       for(int i=0;i<m;i++){ 
           for(int j=0;j<n;j++){ 
             if(test[i][j] && (!test1[i][j])){ 
                 color1(i,j,test,st,0); 

                 }}} 

      // cout<<"\nsum is "<<(sum_max+temp_sum)<<endl<<endl; 
      cout<<(sum_max+temp_sum)<<endl; 
     for(int i=0;i<m;i++){ 
           for(int j=0;j<n;j++){cout<<stamp[i][j]<<" ";} cout<<endl;} 
//   cout<<max<<endl; 
     A.clear(); 
     test.clear(); 
     test1.clear(); 
     sum_max=0; 
      } 


    cout<<endl;system("pause"); 
return 0; 
}