zoukankan      html  css  js  c++  java
  • HDU1425 A Chess Game

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1524

    思路:题目就是给你一个拓扑图,然后指定点的位置放棋子,然后两人轮流移动棋子(题目中的边的关系),直到一方不能移动。

    SG函数裸题,之前接触的两道一个是推的关系,一个是取石子的。这个比较明显的就是出度为0的点,sg值为0。然后深搜得到其他点的sg值,棋子的异或和为0 则P必败,否则N必胜

    由于递归写的很不好,导致没过。最开始竟然用队列随便写了一个。(TLE),后来尝试用dfs写了,WA,迫于无奈只好看题解了(果真就是dfs)  后面附有错误代码

    AC代码:

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <stdlib.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    using namespace std;
    #define in freopen("in.txt", "r", stdin);
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    
    vector<int> G[1010];
    int sg[1010];
    int n, xi, u, v, m, x;
    int dfs(int id) { //为什么感觉不是太难写,自己就是写不出来。   T_T !!!
    	if(sg[id] != -1) return sg[id];//已经有了直接返回 
    	bool vis[1010];//标记,求mex 
    	memset(vis, false, sizeof(vis));
    	for(int i = 0; i < G[id].size(); i++) {
    		sg[G[id][i]] = dfs(G[id][i]);//递归求出后继sg值 
    		vis[sg[G[id][i]]]= true;//标记后继的sg值 
    	}
    	for(int i = 0; ; i++) {
    		if(!vis[i]) {
    			return sg[id] = i;//求自己的sg值 
    		}
    	}
    }
    
    int main() {
    	while(~scanf("%d", &n)) {
    		memset(G, 0, sizeof(G));
    		for(int i = 0; i < n; i++) {
    			scanf("%d", &xi);
    			while(xi--) {//存图 
    				scanf("%d", &v);
    				G[i].push_back(v);
    			}
    		}
    		memset(sg, -1, sizeof(sg));
    		while(scanf("%d", &m) && m) {
    			int sum = 0;
    			while(m--) {//异或和 
    				scanf("%d", &x);
    				sum ^= dfs(x);
    			}
    			if(sum)
    				printf("WIN
    ");
    			else
    				printf("LOSE
    ");
    		}
    	}
    } 
    

    瞎写的队列代码(TLE)

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <stdlib.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    using namespace std;
    #define in freopen("in.txt", "r", stdin);
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    
    vector<int> G[1010];
    int sg[1010];
    int n, xi, u, v, m, x;
    
    void SG() {
    	queue<int> q;
    	for(int i = 0; i < n; i++) {
    		if(G[i].size() == 0)
    			sg[i] = 0;
    		else q.push(i);//需要求的点i 
    	}
    	bool vis[1010];
    	while(!q.empty()) 
    		memset(vis, false, sizeof(vis));
    		int u = q.front();
    		bool flag = false;
    		for(int j = 0; j < G[u].size(); j++) { 
    			if(sg[G[u][j]] != -1) {//如果后继有一个不知道的就换 
    				vis[sg[G[u][j]]] = true;
    			} else {
    				flag = true;
    				q.push(u);
    				q.pop();
    			}
    		}
    		if(flag == false) {//说明这个点的sg值可以求 
    			for(int j = 0; j <= 1010; j++) {
    				if(vis[j] == false) {
    					sg[u] = j;
    					break;
    				}
    			}
    			q.pop();
    		}
    	}
    }
    
    int main() {
    	while(~scanf("%d", &n)) {
    		memset(G, 0, sizeof(G));
    		for(int i = 0; i < n; i++) {
    			scanf("%d", &xi);
    			if(xi == 0)
    				continue;
    			else {
    				while(xi--) {
    					scanf("%d", &v);
    					G[i].push_back(v);
    				}
    			}
    		}
    		memset(sg, -1, sizeof(sg));
    		SG();
    		while(~scanf("%d", &m) && m) {
    			int sum = 0;
    			while(m--) {
    				scanf("%d", &x);
    				sum ^= sg[x];
    			}
    			if(sum)
    				printf("WIN
    ");
    			else
    				printf("LOSE
    ");
    		}
    	}
    } 
    

    自己写的错误DFS代码:

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <stdlib.h>
    #include <string>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    using namespace std;
    #define in freopen("in.txt", "r", stdin);
    typedef long long ll;
    const int inf = 0x3f3f3f3f;
    
    vector<int> G[1010];
    int sg[1010], indegree[1010];
    int n, xi, u, v, m, x, topu;
    vector<int> GB[1010];//该点的 后继值 
    void SG(int id) {
    	for(int i = 0; i < G[id].size(); i++) {//我刚开始也写的bool vis[maxn]  但是我以为这个vis的状态会被破坏 T_T 
    		if(sg[G[id][i]] != -1)
    			GB[id].push_back(sg[G[id][i]]);
    		else {
    			SG(G[id][i]);//瞎写我以为这样求下去,sg[G[id][i]]的值就有了 但是我还是感觉就有了。。。。 
    			GB[id].push_back(sg[G[id][i]]);
    		}
    	}
    	sg[id] = *min_element(GB[id].begin(), GB[id].end()) - 1;//直接求sg值 
    }
    
    int main() {
    	while(~scanf("%d", &n)) {
    		memset(G, 0, sizeof(G));
    		memset(GB, 0, sizeof(GB));
    		memset(indegree, 0, sizeof(indegree));
    		for(int i = 0; i < n; i++) {
    			scanf("%d", &xi);
    			if(xi == 0)
    				continue;
    			else {
    				while(xi--) {
    					scanf("%d", &v);
    					G[i].push_back(v);
    					indegree[v]++;//因为是一个图,我就打算从根节点开始往下搜 
    				}
    			}
    		}
    		memset(sg, -1, sizeof(sg));
    		for(int i = 0; i < n; i++) {
    			if(G[i].size() == 0)
    				sg[i] = 0;
    			else if(indegree[i] == 0)
    				topu = i;//根节点 
    		}
    		SG(topu);
    		while(~scanf("%d", &m) && m) {
    			int sum = 0;
    			while(m--) {
    				scanf("%d", &x);
    				sum ^= sg[x];
    			}
    			if(sum)
    				printf("WIN
    ");
    			else
    				printf("LOSE
    ");
    		}
    	}
    } 
    
  • 相关阅读:
    Java魔法堂:String.format详解
    Postgresql 正则表达式
    Linux下安装LAMP(Apache+PHP+MySql)和禅道
    Redis 启动警告错误解决[转]
    Postgresql: UUID的使用
    在Linux下安装RabbitMQ
    Python的包管理工具Pip
    在Linux CentOS 6.6上安装RedisLive
    [转]在Linux CentOS 6.6上安装Python 2.7.9
    在Linux上rpm安装运行Redis 3.0.4
  • 原文地址:https://www.cnblogs.com/ACMerszl/p/9572947.html
Copyright © 2011-2022 走看看