吴昊品游戏核心算法 Round 11 (增刊) —— 捡花生游戏AI(毫无理性的贪心)(POJ 2950)

这个游戏非常简单,但非常有趣,所以,我在这里不作为Round 12,而将其独立出来,作为一个增刊来放送。这是一款比较老式的游戏了,我曾经在某次过年的时候,在NOKIA的手机上玩过,当时是塞班的系统,画质不怎么样,但是非常有趣。

 玩法简介:

 

 一个直观的想法:

   将整个花生地作为一个二维的整型数组,没有花生的地方标注0而有花生的地方标注花生的数目。一个比较直观的想法就是自变量为时间t和这个二维数组,因变量 为最多可以获得花生数目的函数,当然,这个做法直观,而且可以确定这个函数是存在的(因为满足一一对应的关系),但问题是你建立地出来咩?

 放弃直观的想法,我们开始推理:

 有一种贪心的想法,如果我们一开始就瞄准花生最多的位置,然后再逐渐瞄准花生比较多的位置,依此类推,可否达到最优解呢?显然,我们每次都是尽量地局部最优,但是,局部最优是并不一定可以保证全局最优的,那么,我们不妨简单论证一下我们刚才的想法。

 如果我们一开始放弃花生数目最多的位置而找花生次多的位置,会发生什么?

 假设存在这种情况,那么,我们不能采数目最多花生的理由是什么?(1)时间不够(2)可能会落下在附近的不是次多数目的花生。我们不妨设想一种情况,假设 数目最多花生的旁边有5颗花生,而如果我们要去采更远处的10颗花生的话,等于还要“绕回来”,所以那位老人所说的“每次采数目最多的花生”的贪心策略是 不理智的。但是,由于问题要求我们用老人所说的方式去做,我们就只好将老人的吩咐作为AI咯~这个AI比较弱智,觉得。

 动态规划:

 考虑所有的可能性,并且将一些中间值进行存储,是AI最准备而时间效率尽量高的做法了,贪心简便而迅速,但如果不严格地证明的话,经常会有问题。

  Solve:

  
 1 #include<stdio.h>
 2  #include<stdlib.h>
 3  #include<memory.h>
 4  #include<math.h>
 5  
 6  //定义一个"花生地"的最大长度和宽度(这里上限是50*50)
 7  #define MAX_NUM 55
 8  
 9  int T,M,N,K;
10  int aField[MAX_NUM][MAX_NUM];
11  
12  int main()
13  {
14    //读入对应的案例
15    scanf("%d",&T);
16    for(int t=0;t<T;t++)
17    {
18      scanf("%d%d%d",&M,&N,&K);
19      //这里为了方便描述,将数组的开始标志设为1
20      for(int m=1;m<=M;m++)
21      {
22        for(int n=1;n<=N;n++)
23        {
24          scanf("%d",&aField[m][n]);        
25        }          
26      }        
27      //采摘到的花生总数,这里是一个不错的变量命名
28      int nTotalPeanuts=0;
29      //已经过去的时间
30      int nTotalTime=0;
31      //设置横纵坐标的初始值,横坐标是确定的,而纵坐标不确定
32      int nCuri=0;
33      int nCurj;
34      //直到时间耗尽位置
35      while(nTotalTime<K)
36      {
37        //找到最大花生的数目和所在位置
38        int nMax=0,nMaxi,nMaxj;       
39        for(int i=1;i<=M;i++)
40        {
41          for(int j=1;j<=N;j++)
42          {
43            if(nMax<aField[i][j])
44            {
45              nMax=aField[i][j];
46              nMaxi=i;
47              nMaxj=j;                     
48            }        
49          }        
50        }   
51        //这里一个剪枝,如果地里已经没有花生了,则可以退出         
52        if(nMax==0)
53          break;
54        if(nCuri==0)
55        {
56          //如果我们是在初始阶段的话,那么一个贪心的想法,我们先看看能否走到花生最多的地方
57          nCurj=nMaxj;            
58        }
59        //这里的判断如下,其中的1是采花生的时间,而每次都要确保有时间回来
60        if(nTotalTime+nMaxi+1+abs(nMaxi-nCuri)+abs(nMaxj-nCurj)<=K)
61        {
62          //追加时间
63          nTotalTime+=1+abs(nMaxi-nCuri)+abs(nMaxj-nCurj);
64          //走到新的位置
65          nCuri=nMaxi;
66          nCurj=nMaxj;
67          //追加采到的花生的总数
68          nTotalPeanuts+=aField[nMaxi][nMaxj];
69          //采走花生
70          aField[nMaxi][nMaxj]=0;                                                           
71        }
72        else break;
73      }
74      printf("%d\n",nTotalPeanuts);
75    }
76    return 0;   
77  }

posted on 2013-02-28 13:25  吴昊系列  阅读(221)  评论(0编辑  收藏  举报

导航