zoukankan      html  css  js  c++  java
  • 「BJOI2018」双人猜数游戏(博弈+dp)

    https://loj.ac/problem/2511

    不知道很多轮后就知道了是因为可能的数对在不断减少。

    考虑设(f[z][x][y])表示(z)轮后,两个数分别为(x,y)是否能猜出来。

    (z=1)时,(f=可能的数对(u,v)只有一个)

    (z>1)
    转移1:(f[z][x][y]=f[z-2][x][y])
    转移2:枚举所有可能的数对((u,v)),若((u,v)(除(x,y)))(z-1)轮都被猜出来,则(f[z][x][y]=1)

    最后,答案要的是两个人都知道的时间是(t+1)(t+2)

    ((x,y))合法的条件:
    ((x,y))最早知道时间是(t+1),且对于所有可能的数对((u,v)),只有((x,y))(t+1)知道,那么(t+2)时另一人就可以知道。

    利用记忆话搜索+map可以(1s)内出所有解,

    Code

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    string in, out, num;
    
    void init(int t) {
    	num = "";
    	for(; t; t /= 10) num = ((char) (t % 10 + '0')) + num;
    	in = "guess" + num + ".in";
    	out = "guess" + num + ".out";
    }
    
    int s, t; char str[105];
    
    const int N = 100005;
    
    map<int, int> bz[18][N], f[18][N];
    
    int dg(int z, int x, int y) {
    	if(bz[z][x][y]) return f[z][x][y];
    	bz[z][x][y] = 1;
    	if(z == 1) {
    		if(str[0] == 'A') {
    			int cnt = 0;
    			fo(i, s, x * y) if(x * y % i == 0 && i <= x * y / i)
    				cnt ++;
    			f[z][x][y] = cnt == 1;
    		} else {
    			int cnt = 0;
    			fo(i, s, x + y) if(i <= x + y - i)
    				cnt ++;
    			f[z][x][y] = cnt == 1;
    		}
    		return f[z][x][y];
    	}
    	f[z][x][y] = z > 2 ? dg(z - 2, x, y) : 0;
    	if(!f[z][x][y]) {
    		if(((str[0] == 'A') + z) % 2 == 0) {
    			int cnt = 0;
    			fo(i, s, x * y) if(x * y % i == 0 && i <= x * y / i) {
    				cnt += !dg(z - 1, i, x * y / i);
    			}
    			if(cnt == 1 && !dg(z - 1, x, y))
    				f[z][x][y] = 1;
    		} else {
    			int cnt = 0;
    			fo(i, s, x + y) if(i <= x + y - i) {
    				cnt += !dg(z - 1, i, x + y - i);
    			}
    			if(cnt == 1 && !dg(z - 1, x, y))
    				f[z][x][y] = 1;
    		}
    	}
    	return f[z][x][y];
    }
    
    int n;
    
    int qry(int x, int y) {
    	fo(i, 1, t + 1) if(dg(i, x, y))
    		return i;
    	return -1;
    }
    
    void work() {
    	fo(i, 1, 17) fo(j, 1, 1e5) bz[i][j].clear();
    	scanf("%d", &s);
    		scanf("%s", str);
    		scanf("%d", &t);
    		fo(sum, 2 * s, 100000) {
    			fo(x, s, sum / 2) {
    				int y = sum - x;
    				if(qry(x, y) == t + 1) {
    					int cnt = 0;
    					if(((str[0] == 'A') + t) % 2 == 0) {
    						int cnt = 0;
    						fo(i, s, x * y) if(x * y % i == 0 && i <= x * y / i) {
    							cnt += (qry(i, x * y / i) == (t + 1));
    						}
    						if(cnt == 1) {
    							pp("%d %d
    ", x, y);
    							return;
    						}
    					} else {
    						int cnt = 0;
    						fo(i, s, x + y) if(i <= x + y - i) {
    							cnt += (qry(i, x + y - i) == (t + 1));
    						}
    						if(cnt == 1) {
    							pp("%d %d
    ", x, y);
    							return;
    						}
    						
    					}
    				}
    			}
    		}
    }
    
    int main() {
    	fo(T, 1, 25) {
    		fprintf(stderr, "%d
    ", T);
    		init(T);
    		freopen(in.c_str(), "r", stdin);
    		freopen(out.c_str(), "w", stdout);
    		work();
    	}
    	
    }
    
  • 相关阅读:
    【cocos】添加监听函数,先使用handle封装函数更优
    【cocos】PC端没问题,移动端人物模型消失
    【lua】lua string.match 和 string.split 从字符串中寻找特定字符串并保存
    APP测试通用用例--我的(用户角色全选、资料、修改密码、版本更新、消息提醒、关于APP、清除缓存等)
    APP通用测试用例(一)-登录和页面展示
    Django学习(一)-sign下的Hello Django!
    Django学习(一)
    如何快速去掉word中的文字被标红或者是显示成下划线
    在与SQLServer建立连接时出现与网络相关的或特定于实例的错误解决
    使用mdf和ldf附加还原SQL Server数据文件
  • 原文地址:https://www.cnblogs.com/coldchair/p/12696822.html
Copyright © 2011-2022 走看看