zoukankan      html  css  js  c++  java
  • ACM-ICPC 2018 徐州赛区网络预赛 B BE, GE or NE 【模拟+博弈】

    题目:戳这里

    题意:A和B博弈,三种操作分别是x:加a,y:减b,z:取相反数。当x或y或z为0,说明该操作不可取,数据保证至少有一个操作可取,给定一个区间(l,k)和原始数字m,如果A和B在n次操作以后使m小于等于l,则B赢,大于等于k则A赢。如果A或B实在赢不了,就会尽量让对方也没法赢。

    解题思路:因为数据范围始终在[-100,100],我们就有了逆推的想法。思路是假如n=3且A必赢。因为我们假设的是A必赢,那么第三步之后的m一定在nu3:[k,100]之间,又因为第三步是A的操作,A肯定是哪步操作可以赢,就使用哪步操作,所以第三步以前的范围nu2是根据第三步以后的范围nu3:[k,100]对所有操作逆推出来的集合求并。据此从nu3逆推出nu2。

    第三步之间就是第二步,第二步是B的操作,B如果有任何机会肯定是不会让A赢的,所以第二步之前的范围nu1是第二步以后nu2对所有操作逆推出来的集合求交。

    nu1同nu3的推法。

    第二种情况就是B必赢。也是和上面的思路一样推,如果A必赢和B必赢都无法满足,那一定是在(l,k)之间了。

    看代码更好理解。

    附ac代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn = 1e3 + 10;
      4 typedef long long ll;
      5 int nu[maxn][11];
      6 int ans[2][555];
      7 int main()
      8 {
      9     int n, now ,l ,k;
     10     scanf("%d %d %d %d", &n, &now, &k, &l);
     11     for(int i = 1; i <= n; ++i)
     12     {
     13         scanf("%d %d %d", &nu[i][1], &nu[i][2], &nu[i][3]);
     14     }
     15     //B win
     16     for(int j = -100; j <= 100; ++j)
     17     {
     18         if(j <= l)
     19         ans[n & 1][j + 200] = 1;
     20         else
     21         ans[n & 1][j + 200] = 0;
     22     }
     23     for(int i = n; i >= 1; --i)
     24     {
     25         memset(ans[(i&1)^1], 0, sizeof(ans[(i&1)^1]));
     26         for(int j = -100; j <= 100; ++j)
     27         {
     28                 if(i&1)
     29                 {
     30                     int flag = 0;
     31                     if(nu[i][1])
     32                     {
     33                         int u = min(j + nu[i][1], 100);
     34                         if(!ans[i&1][u + 200])   flag++;
     35                     }
     36                     if(nu[i][2])
     37                     {
     38                         int u = max(j - nu[i][2], -100);
     39                         if(!ans[i&1][u + 200])   flag++;
     40                     }
     41                     if(nu[i][3])
     42                     {
     43                         int u = j * -1;
     44                         if(!ans[i&1][u + 200])   flag++;
     45                     }
     46                    // printf("%d %d %d %d
    ", i, j, flag, ans[i&1][j + 200]);
     47                     if(!flag)   ans[(i&1) ^ 1][j + 200] = 1;
     48                 }
     49                 else
     50                 {
     51                     int flag = 0, v = 0;
     52                     if(nu[i][1])
     53                     {
     54                         ++v;
     55                         int u = min(j + nu[i][1], 100);
     56                         if(!ans[i&1][u + 200])   flag++;
     57                     }
     58                     if(nu[i][2])
     59                     {
     60                         ++v;
     61                         int u = max(j - nu[i][2], -100);
     62                         if(!ans[i&1][u + 200])   flag++;
     63                     }
     64                     if(nu[i][3])
     65                     {
     66                         ++v;
     67                         int u = j * -1;
     68                         if(!ans[i&1][u + 200])   flag++;
     69 
     70                     }
     71                    // printf("%d %d %d u %d
    ", i, j, flag == v, l);
     72                     if(flag != v)   ans[(i&1) ^ 1][j + 200] = 1;
     73 
     74                 }
     75         }
     76     }
     77     int bwin = 0;
     78     for(int i = -100; i <= 100; ++i)
     79     {
     80        // printf("%d %d
    ", i, ans[0][i + 200]);
     81         if(ans[0][i + 200] && i == now)
     82         {
     83             ++bwin;
     84             break;
     85         }
     86     }
     87     for(int i = -100; i <= 100; ++i)
     88     {
     89         if(i >= k)
     90         ans[n & 1][i + 200] = 1;
     91         else
     92         ans[n & 1][i + 200] = 0;
     93     }
     94 
     95     for(int i = n; i >= 1; --i)//a win
     96     {
     97         memset(ans[(i&1)^1], 0, sizeof(ans[(i&1)^1]));
     98         for(int j = -100; j <= 100; ++j)
     99         {
    100             if(i & 1)
    101             {
    102                 int flag = 0 ,v = 0;
    103                 if(nu[i][1])
    104                 {
    105                     ++v;
    106                     int u = min(j + nu[i][1], 100);
    107                     if(!ans[i&1][u + 200])   flag++;
    108                 }
    109                 if(nu[i][2])
    110                 {
    111                     ++v;
    112                     int u = max(j - nu[i][2], -100);
    113                     if(!ans[i&1][u + 200])   flag++;
    114                 }
    115                 if(nu[i][3])
    116                 {
    117                     ++v;
    118                     int u = j * -1;
    119                     if(!ans[i&1][u + 200])   flag++;
    120                 }
    121               // printf("%d %d %d v %d
    ", i, j, flag == v, ans[i&1][j + 200]);
    122                 if(flag != v)   ans[(i&1) ^ 1][j + 200] = 1;
    123             }
    124             else
    125             {
    126                 int flag = 0;
    127                 if(nu[i][1])
    128                 {
    129                     int u = min(j + nu[i][1], 100);
    130                     if(!ans[i&1][u + 200])   flag++;
    131                 }
    132                 if(nu[i][2])
    133                 {
    134                     int u = max(j - nu[i][2], -100);
    135                     if(!ans[i&1][u + 200])   flag++;
    136                 }
    137                 if(nu[i][3])
    138                 {
    139                     int u = j * -1;
    140                     if(!ans[i&1][u + 200])   flag++;
    141                 }
    142                // printf("%d %d %d %d
    ", i, j, flag, ans[i&1][j + 200]);
    143                 if(!flag)   ans[(i&1) ^ 1][j + 200] = 1;
    144             }
    145         }
    146     }
    147     int awin = 0;
    148     for(int i = -100; i <= 100; ++i)
    149     {
    150         if(ans[0][i + 200] && i == now)
    151         {
    152             ++awin;
    153             break;
    154         }
    155     }
    156     //printf("%d %d
    ", awin, bwin);
    157     if(!awin && !bwin)  puts("Normal Ending");
    158     if(awin)    puts("Good Ending");
    159     if(bwin)    puts("Bad Ending");
    160     return 0;
    161 }
    View Code
  • 相关阅读:
    beta冲刺5
    beta冲刺4
    beta冲刺3
    beta冲刺2
    [LeetCode] 10. Regular Expression Matching(正则匹配)
    [LeetCode] 32. Longest Valid Parentheses(最长合法括号对)
    [LeetCode] 4. Median of Two Sorted Arrays.(两个有序数组的中位数)
    [LeetCode] 45. Jump Game Ⅱ(跳跃游戏之二)
    [LeetCode] 41. First Missing Positive(第一个缺失的正数)
    [LeetCode] 124. Binary Tree Maximum Path Sum(二叉树的最大路径和)
  • 原文地址:https://www.cnblogs.com/zmin/p/9620344.html
Copyright © 2011-2022 走看看