UVa 12418 - Game of 999
来源:互联网 发布:中国海关进出口数据库 编辑:程序博客网 时间:2024/05/22 04:27
博主本来只想虐虐NOIP级别的暴力的.........
1. 本题状态很简单 , 哪些边用了 , 现在各点在哪里 , 把vector状态压缩成一个long long(代码中的ull 是 long long).
2. 转移的思路不复杂 , 看看哪些点能够从某一房间转移到另外一些房间 (不知道不预处理的版本能不能过 , 但是博主进行了一次预处理)
写写吧 , 虽然肯定超时 , 但是正解离你将要写的代码修改的不过3,4行 , 写完后尝试以下数据
就这样写 , 样例跑的很快 , 但是有一组数据肯定过不了
10 10
1 2 0
2 3 0
3 4 0
4 5 0
5 6 0
6 7 0
7 8 0
8 9 0
9 10 0
10 1 0
(博主想了各种优化方法 , 但是这个复杂度需要的优化不是常数级别的 , 也就是题目中的hint 所说的)
观察发现 , 其实状态是很有限的 , 因为很多路都只能经过一次 , 有用的状态尤其有限 (比如上述数据中从1到10然后回到1肯定是无用状态)
那该怎么处理呢? 请思考些时间 , 提示: 无用的状态是什么造成的
如果有思路了就动手吧 , 下面是代码 , 余下的所有分析在代码后
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <string>#include <vector>#include <deque>#include <stack>#include <algorithm>#include <set>#include <queue>#include <list>using namespace std;typedef long long ull;const int maxn = 12;const int maxm = 12;int n , m;int u[maxm] , v[maxm] , w[maxm];vector<int> g[maxn];int allow[maxm][1<<maxn];ull q[10000000];set<ull> dic;ull encode(vector<int>& s){ull res = 0;for(int i=1;i<s.size();i++) res = res*11+s[i];res = res*1200+s[0];return res;}void decode(vector<int>& s , ull v){s[0] = v%1200; v/=1200;for(int i=(int)s.size()-1;i>=1;i--) s[i] = v%11 , v/=11;}int reachable[maxn][maxn];int main(int argc, char *argv[]) {while(cin>>n>>m){dic.clear();memset(allow, 0, sizeof(allow));for(int i=1;i<=n;i++) g[i].clear(); memset(reachable, 0, sizeof(reachable)); for(int i=1;i<=m;i++) { cin>>u[i]>>v[i]>>w[i]; if(w[i]) g[u[i]].push_back(i); else reachable[u[i]][v[i]] = 1; }for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) reachable[i][j] |= ( reachable[i][k] && reachable[k][j] );for(int i=1;i<(1<<9);i++) if(__builtin_popcount(i)>=3 && __builtin_popcount(i)<=5){int num = 0;for(int j=1;j<=9;j++) if(i&(1<<(j-1))) num+= j;while(num>=10) num = num/10+num%10;for(int j=1;j<=m;j++) if(w[j]==num) allow[j][i] = 1;}for(int j=1;j<=m;j++) if(w[j]==0) for(int i=1;i<512;i++) allow[j][i] = 1;int book[maxn];vector<int> beg;set<int> ans; int Max = 0;beg.push_back((1<<m)-1);for(int i=1;i<=9;i++) beg.push_back(1);int l = 0 , r = 0;q[r++] = encode(beg);dic.insert(encode(beg));while(l!=r){vector<int> now = beg , ne;decode(now, q[l++]);memset(book, 0, sizeof(book));for(int i=1;i<now.size();i++) book[now[i]] |= (1<<(i-1));for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(reachable[i][j]) book[j] |= book[i]; if(book[n] && __builtin_popcount(book[n])>Max) { Max = __builtin_popcount(book[n]); ans.clear(); ans.insert(book[n]); }else if(book[n] && __builtin_popcount(book[n])==Max) if(ans.count(book[n])==0) ans.insert(book[n]);for(int i=1;i<=n;i++) for(int j=0;j<g[i].size();j++){int way = g[i][j] , to = v[way];if(!(now[0]&(1<<(way-1)))) continue;for(int s = book[i];s>0;s = (s-1)&book[i]) if(allow[way][s]){ne = now;for(int l=1;l<=9;l++) if(s& (1<<(l-1))) ne[l] = to;if(w[way]) ne[0]^= 1<<(way-1);ull hashNow = encode(ne);if(dic.count(hashNow)) continue;dic.insert(hashNow);q[r++] = encode(ne);}}}vector<string> output;for(set<int>::iterator i=ans.begin();i!=ans.end();++i) {int now = *i; string ins;for(int j=1;j<=9;j++) if(now&(1<<(j-1))) ins = ins+((char)(j+'0'));output.push_back(ins); } sort(output.begin(), output.end()); cout<<Max;for(int i=0;i<output.size();i++) cout<<" "<<output[i]; cout<<endl; }return 0;}
剩下的就是floyd判通 , 然后稍稍修改代码就可以啦
0 0
- UVa 12418 - Game of 999
- Game of Sum UVA
- uva 10891 Game of Sum
- UVA 10891 Game of Sum
- UVa 10891 Game of Sum
- Uva-10891-Game of Sum
- Uva 10891 Game of Sum
- Uva - 10891 - Game of Sum
- uva 10891 - Game of Sum
- uva 10891 game of sum
- UVA 10891 Game of Sum
- UVa 10891 - Game of Sum
- UVA 10891 Game of Sum
- uva 10891 - Game of Sum
- UVA - 10891 Game of Sum
- uva 10891 - Game of Sum
- uva 10891 - Game of Sum
- UVA 10891 Game of Sum
- C++ STL算法系列1---count函数
- 【大渣】【多维KMP】奶牛阵列
- Java NIO——Selector机制源码分析---转
- 【Linux学习】epoll详解
- IUnknown
- UVa 12418 - Game of 999
- js常用返回刷新脚本
- spring源码剖析(一)下载spring3.2源代码,并编译源代码
- Android 中webp 的使用
- Qin Shi Huang's National Road System
- 安家了!第一篇自己的博客
- 关于英雄联盟中的英雄是如何寻找最佳路径的
- 局域网所有IP
- python 核心编程第二版 9-9