zoukankan      html  css  js  c++  java
  • Topcoder 12519 ScotlandYard(点对 dp+最长路)

    题面传送门

    题意: 有两个人 A 和 B 玩一个游戏。游戏规则大致是这样的: 有 (n) 个城市和三种交通工具公交、地铁和出租车。 给出三个 (n imes n) 的字符矩阵 (b,m,t)(b_{i,j}='Y') 表示从城市 (i) 可以通过公交到达城市 (j)(b_{i,j}='N') 表示从城市 (i) 不可以通过公交到达城市 (j)(m,t) 同理。 现在 A 要选择一个起始城市 (i),但是 B 不知道这个城市的编号。小 A 每次可以通过某种交通工具到达另一个城市,并将乘坐的交通工具告诉 B。如果 B 猜出了小 A 当前所在的城市,或者小 B 动不了了,游戏结束。 A 的得分为 A 经过的边数。求 A 得分的最大值,如果游戏可能永远进行下去,输出 -1。 (1 leq n leq 50)

    话说这题出现了两次呢。。。记得 CSP 前一周学校模拟赛某道题就是这个,结果昨天模拟赛又出现了一遍。。。今天终于见到这题的真面貌了( 记 (S) 为当前 A 当前可能位于的城市的集合。初始 (S={1,2,dots,n})。 如果小 A 搭乘了交通工具 (x),那么 (S) 就变为:(S) 中的点集通过交通工具 (x) 能到达的点。 答案就是最多进行多少次操作后 (S) 中剩一个点。 很容易想到 (2^n) 的做法,对于集合之间的相互转化关系连边,跑最长路。


    其实并不用把集合中每个点都表示出来。 只需要找到两个代表点 ((i,j)),对这些点对连边跑最长路就行了。 这样点的个数就降到了 (n^2)。 至于 (-1) 的情况,就是判断对点对建立的图中有没有环,记忆化搜索/拓扑排序就可以了。 时间复杂度 (n^4),是道思维题(为啥就想不出来呢,wtcl)

    #include <bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define fz(i,a,b) for(int i=a;i<=b;i++)
    #define fd(i,a,b) for(int i=a;i>=b;i--)
    #define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
    #define fill0(a) memset(a,0,sizeof(a))
    #define fill1(a) memset(a,-1,sizeof(a))
    #define fillbig(a) memset(a,63,sizeof(a))
    #define pb push_back
    #define ppb pop_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    const int MAXN=50+5;
    int n,dp[MAXN][MAXN],vis[MAXN][MAXN];
    bool s1[MAXN][MAXN],s2[MAXN][MAXN],s3[MAXN][MAXN];
    int dfs(int x,int y){
    	if(x>y) swap(x,y);
    	if(x==y) return 0;
    	if(vis[x][y]) return 1e9;
    	if(~dp[x][y]) return dp[x][y];
    	vis[x][y]=1;dp[x][y]=0;
    	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){
    		if((s1[x][i]&&s1[y][j])||(s1[x][i]&&s1[x][j])||(s1[y][i]&&s1[y][j])||
    		   (s2[x][i]&&s2[y][j])||(s2[x][i]&&s2[x][j])||(s2[y][i]&&s2[y][j])||
    		   (s3[x][i]&&s3[y][j])||(s3[x][i]&&s3[x][j])||(s3[y][i]&&s3[y][j]))
    				dp[x][y]=max(dp[x][y],dfs(i,j)+1);
    	}
    	vis[x][y]=0;return dp[x][y];
    }
    class ScotlandYard{
    public:
    	int maxMoves(vector<string> taxi,vector<string> bus,vector<string> metro){
    		n=taxi.size();
    		for(int i=0;i<n;i++) for(int j=0;j<n;j++) s1[i+1][j+1]=(taxi[i][j]=='Y');
    		for(int i=0;i<n;i++) for(int j=0;j<n;j++) s2[i+1][j+1]=(bus[i][j]=='Y');
    		for(int i=0;i<n;i++) for(int j=0;j<n;j++) s3[i+1][j+1]=(metro[i][j]=='Y');
    		int ans=0;memset(dp,-1,sizeof(dp));
    		for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) ans=max(ans,dfs(i,j));
    		if(ans>=1e9) return -1;return ans;
    	}
    };
    //ScotlandYard program;
    //int main(){
    //	int n;scanf("%d",&n);
    //	vector<string> taxi,bus,metro;
    //	for(int i=1;i<=n;i++){string s;cin>>s;taxi.pb(s);}
    //	for(int i=1;i<=n;i++){string s;cin>>s;bus.pb(s);}
    //	for(int i=1;i<=n;i++){string s;cin>>s;metro.pb(s);}
    //	printf("%d
    ",program.maxMoves(taxi,bus,metro));
    //	return 0;
    //}
    
  • 相关阅读:
    【spring-boot】spring-boot 事物管理——之注解@Transactional
    【spring-boot】Spring-boot学习-helloWorld
    【Maven】failOnMissingWebXml
    【java基础领域】高内聚、低耦合理解
    Pascal's Triangle
    Remove Nth Node From End of List
    Valid Palindrome
    Longest Common Prefix
    Roman to Integer
    Palindrome Number
  • 原文地址:https://www.cnblogs.com/ET2006/p/Topcoder-12519.html
Copyright © 2011-2022 走看看