1085 Triangle War

题目大意是2个人玩一种游戏,每次放1条边,如果生成了三角形,则归他所有

给定一些初始的走法,问都以最优策略走谁最后拿的三角形多?

很早做的,有点难度,详细注释

dp,或者说是博弈

  1. //4448583_AC_485MS_1468K
  2. /**********************************************************************
  3. *       Online Judge   : POJ
  4. *       Problem Title  : Triangle War
  5. *       ID             : 1085
  6. *       Date           : 12/3/2008
  7. *       Time           : 8:23:54
  8. *       Computer Name  : EVERLASTING-PC
  9. ***********************************************************************/
  10. /*
  11. 线段使用二进制存储,2^i表示第i条线段的hash值
  12. 0<=state<2^18,二进制表示当前棋盘状态
  13. f(state) 表示在state这个状态下,A先走,双方走法都是最优,最终A比B多得到的三角形个数
  14. 0<=i<18,记place(state,2^i)=t,则
  15. f(state)=max
  16. {
  17. -f(state|2^i)   当t=0
  18. t +f(state|2^i) 当t>0
  19. }
  20. */
  21. #include<iostream>
  22. using namespace std;
  23. //储存组成每个三角形的线段hash值
  24. int tri[9][3]=
  25. {
  26.     {0x1,0x2,0x4},
  27.     {0x4,0x10,0x20},
  28.     {0x8,0x10,0x80},
  29.     {0x20,0x40,0x100},
  30.     {0x200,0x400,0x8000},
  31.     {0x80,0x400,0x800},
  32.     {0x800,0x1000,0x10000},
  33.     {0x100,0x1000,0x2000},
  34.     {0x2000,0x4000,0x20000}
  35. };
  36. //存线段端点标号
  37. int line[18][2]=
  38. {
  39.     {1, 2},{1, 3},{2, 3},{2, 4},{2, 5},{3, 5},
  40.     {3, 6},{4, 5},{5, 6},{4, 7},{4, 8},{5, 8},                                 
  41.     {5, 9},{6, 9},{6, 10},{7, 8},{8, 9},{9, 10}
  42. };
  43. //2的幂
  44. int exp2[18]=
  45. {
  46.     0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80,0x100,0x200,0x400,0x800,0x1000,0x2000,0x4000,0x8000,0x10000,0x20000
  47. };
  48. /*
  49. 全局变量
  50. f[] 将f()的值存下,避免重复计算
  51. state 当前棋盘状态
  52. MIN 初始化的极小值
  53. */
  54. int f[0x40000];
  55. int state;
  56. const int MIN=-10;
  57. //计算在state这个状态下,放置某线段新得到的三角形数
  58. int place(int state,int hash)
  59. {
  60.     int already,t,get=0;
  61.     for(int i=0;i<9;++i)
  62.     {
  63.         already=0;t=3;
  64.         for(int j=0;j<3;++j)
  65.         {
  66.             //放置的线段是第i个三角形中的第j条
  67.             if(tri[i][j]&hash)
  68.             {
  69.                 t=j;
  70.             }
  71.             //第i个三角形中的第j条已经放置
  72.             else if(tri[i][j]&state)
  73.             {
  74.                 already++;
  75.             }
  76.         }
  77.         //不存在于第i个三角形中
  78.         if(t==3)
  79.         {
  80.             continue;
  81.         }
  82.         //则第i个三角形是新得到的
  83.         if(already==2)
  84.         {
  85.             get++;
  86.         }
  87.     }
  88.     return get;
  89. }
  90. //f()
  91. int dp(int state)
  92. {
  93.     //如果当前状态已算过就直接用
  94.     if(f[state]!=MIN)
  95.     {
  96.         return f[state];
  97.     }
  98.     int max=MIN,t;
  99.     for(int i=0;i<18;++i)
  100.     {
  101.         //如果第i条线段没有用过
  102.         if(!(state&exp2[i]))
  103.         {
  104.             //放置第i条线段
  105.             t=place(state,exp2[i]);
  106.             //递归计算
  107.             t+=((t)?1:-1)*dp(state|exp2[i]);
  108.             //更新最大值
  109.             max=(t>max)?t:max;
  110.         }
  111.     }
  112.     //存下当前状态的最大值,并返回
  113.     return (f[state]=max);
  114. }
  115. int main()
  116. {
  117.     //freopen("in_1085.txt","r",stdin);
  118.     //全局初始化
  119.     for(int i=0;i<0x40000;++i)
  120.     {
  121.         f[i]=MIN;
  122.     }
  123.     f[0x3FFFF]=0;
  124.     /*
  125.     b 数据块数
  126.     n 每块的局数
  127.     m 每局已经走的步数
  128.     x,y 读入的线段
  129.     t 临时变量
  130.     player 表示当前谁走(1 A,-1 B)
  131.     pre 根据给出的步骤A比B多得到的三角形数
  132.     */
  133.     int b,n,m,x,y,t,player,pre;
  134.     //cin>>b;
  135.     //for(int i=0;i<b;++i)
  136.     {
  137.         cin>>n;
  138.         for(int j=0;j<n;++j)
  139.         {
  140.             //每局初始化
  141.             pre=0;
  142.             state=0;
  143.             player=1;
  144.             cin>>m;
  145.             for(int k=0;k<m;++k)
  146.             {
  147.                 //读入线段
  148.                 cin>>x>>y;
  149.                 for(int l=0;l<18;++l)
  150.                 {
  151.                     //转化为hash并放置
  152.                     if(line[l][0]==x&&line[l][1]==y)
  153.                     {
  154.                         t=place(state,exp2[l]);
  155.                         state|=exp2[l];
  156.                         break;
  157.                     }
  158.                 }
  159.                 //新得到三角形
  160.                 if(t)
  161.                 {
  162.                     pre+=(player*t);
  163.                 }
  164.                 //没有生成新三角形则换另一方走
  165.                 else
  166.                 {
  167.                     player*=-1;
  168.                 }
  169.             }
  170.             //计算状态并输出,>0即A胜
  171.             cout<<"Game "<<j+1<<": "<<((pre+player*dp(state)>0)?'A':'B')<<" wins./n";
  172.         }
  173.         cout<<endl;
  174.     }
  175. }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值