zoukankan      html  css  js  c++  java
  • 训练报告 18春组队04 2014西安全国邀请赛

    Solved A HDU 4847 Wow! Such Doge!
    Solved B HDU 4848 Wow! Such Conquering!
    Solved C HDU 4849 Wow! Such City!
    Solved D HDU 4850 Wow! Such String!
      E HDU 4851 Wow! Such Precision!
      F HDU 4852 Wow! Such Tetris!
      G HDU 4853 Trader Dogy
      H HDU 4854 Round-table Conference
      I HDU 4855 Goddess
    Solved J HDU 4856 Tunnels

    题目链接

    要有求胜意志和竞技心态.....

    B样例没看懂,但是自己按照题意分析了下,如果是直接暴力,30!铁定炸,状态压缩dp n^2*2^30也会炸,就放弃了

    实际上可以用强力剪枝剪过去,不知道那些出题人是如何精准的算出这种题剪枝后复杂度的...好神奇

    C WA了2发才AC,第一次是因为没关调试信息.....而且我数组开小了,他居然返回了WA而不是RE...然后就又WA了一次,最后才发现数组问题,这种水题居然写了这么久...也是跪了

    D交给队友想了,期间队友想出了26^4是最大限度,但是我觉得应该都存在,也是脑残,明显26^4中,任何4的串都出现过的...当时如果写D的话,我应该(可)能怼出来个暴力吧

    J觉得就是搜索,读题读的比B早,想把图和点抽象出来,成一个只有隧道的的小图,应该可以暴力,但是写出来想不到怎么剪枝,怼了好久才发现是个裸的不反回的TSP问题,状态压缩DP写的太少,没调出来...

    其实J一开始就看出来是个NPC问题,NPC问题+15个点,2^15*n^2不会TLE,很明显的状态压缩,我居然活生生写了1小时的暴搜才转正...

    菜啊...

    当然,这次的最大的问题是,缺少求胜心态,对于难题不想怼...看出来是个状压之后瞬间不想写了,不应该的,无论是练习赛还是什么,都应该全力以赴,写到最后一秒..

    1.要有求胜意志和竞技心态.....

    2.状态压缩Dp这种东西,就算成铜牌题,也没啥奇怪的,不应该只抱着什么并查集,最短路,生成树,kmp不放,然后意淫自己混个铜滚粗,不存在,说想拿银就得有银的水平,银牌区大佬现场能写出来的,都得去练去做..

    3.高级算法不可怕,可怕的是学了之后,比赛打得太少,结果写不出来...或者是之前写过的,结果比赛没看出来/没写出来...比如J的数据量一看,傻子都知道是状压DP,亏我还写过TSP呢..

    4.组队打3星题意义不大,只能自我安慰

    5.要有求胜意志和竞技心态.....得多打紧脏刺激的个人赛

    补题:

    B

    可以有一个很强的剪枝,

    因为求的是累加和

    所以前几个点会被重复叠加,所以用公式进行压缩和之前的最优解进行比较,可以在一下子就吧非最优解剪枝掉

    除此之外,对截止时间的可行性剪枝也是必须的...

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=50;
    const int maxm=5e6+10;
    const int len=26*26*26*26;
    const int INF=0x3f3f3f3f;
    int casn,n,m,k;
    int g[maxn][maxn];
    int dl[maxn];
    int ans;
    int vis[maxn];
    int mxdl;
    void dfs(int now,int sum,int dis,int num){
    	if(sum+dis*(n-num)>=ans) return;
    	if(dis>dl[now]) return;
    	for(int i=2;i<=n;i++){
    		if(!vis[i]&&dis+g[now][i]>dl[i]) return;
    	}
    	if(num==n){
    		ans=min(ans,sum);
    	 	return ;
    	}
    	for(int i=1;i<=n;i++){
    		if(!vis[i]){
    			vis[i]=1;
    			dfs(i,sum+dis+g[now][i],dis+g[now][i],num+1);
    			vis[i]=0;
    		}
    	}
    }
    
    int main(){
    //#define test
    #ifdef test
    	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    
    	while(cin>>n){
    		mxdl=0;
    		memset(g,0x3f,sizeof g);
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n;j++){
    				cin>>g[i][j];
    			}
    		}
    		for(int k=1;k<=n;k++){
    			for(int i=1;i<=n;i++){
    				for(int j=1;j<=n;j++){
    					g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
    				}
    			}
    		}
    		for(int i=2;i<=n;i++){
    			cin>>dl[i];
    			mxdl=max(dl[i],mxdl);
    		}
    		ans=INF;
    		memset(vis,0,sizeof vis);
    		vis[1]=1;
    		dfs(1,0,0,1);
    		if(ans==INF) puts("-1");
    		else cout<<ans<<endl;
    	}
    
    #ifdef test
    	fclose(stdin);fclose(stdout);system("out.txt");
    #endif
    	return 0;
    }
    

    D

    我比赛的时候脑子抽筋了,认为D是可以存在无限长度的..结果整个队伍的时间都在J上了,让J霸占了所有机时,很亏

    其实给D一个机会应该(可)能写出来的......

    我们要找一个最长的,首先考虑,如果把4和4以下的排列全部输出了,4以上显然是不存在的,因为长度4以上肯定包含一个出现过的子串...

    那可以确定是存在无解的,大概就是26^4这么长左右

    但是26^4中 是否一定会出现首位相接的排列导致重复子串呢...

    不一定,很显然,我们最长的情况是构造一个字符串,遍历了所有长度为4的排列

    然后,我们这样想...把每2个长度为4的字符串(aaaa) (baaa) 看成一个点(aaa)和一个边(a) 另一个点(baa)以及他向后面点的边(a)

    显然,每个点 可以在它的前面和后面各连一个边(a-z) 换句话说,所有点的度数都是....偶数

    //(aaa)这种 显然只能连一个(a)边,因为是回文的..但是度数依然是偶数的

    根据欧拉回路的性质

    "无向图所有点的度数均为偶数时,必然存在一条欧拉回路"

    至于..为啥是欧拉路不是欧拉回路...

    一个很精髓的地方到了,如果是欧拉路,那就是遍历所有的排列 26^4,最大长度26^4

    但是,但是,如果是欧拉回路,你就能回到起点了!!比如从aaa出发最后到zzz 你的长度肯定是26^4 然后 因为是回路,你可以回到起点,也就是再走一个aaa

    最终长度是26^4+3 !!!

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=27;
    const int maxm=5e6+10;
    const int len=26*26*26*26;
    const int INF=0x3f3f3f3f;
    int casn,n,m,k;
    char p[256][256][256];
    int s[5];
    
    int main(){
    //#define test
    #ifdef test
    	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    
    	while(~scanf("%d",&n)){
    		if(n>len+3) {
    			puts("Impossible");
    			continue;
    		}
    		s[0]=s[1]=s[2]=25;
    		for(int i=0;i<=25;i++){
    			for(int j=0;j<=25;j++){
    				for(int k=0;k<=25;k++){
    			 		p[i][j][k]=0;
    				}
    			}
    		}
    		for(int i=0;i<min(n,3);i++){
    			putchar((char)(s[i]+'a'));
    		}
    		for(int i=3;i<n;i++){
    			s[(i-1)%3]=p[s[(i-3)%3]][s[(i-2)%3]][s[(i-1)%3]]++;
    			putchar((char)(s[(i-1)%3]+'a'));
    		}
    		puts("");
    	}
    
    #ifdef test
    	fclose(stdin);fclose(stdout);system("out.txt");
    #endif
    	return 0;
    }
    

    J

    裸的TSP问题,只不过不用回到起点,初始化改一改就行,期间用bfs求距离 复杂度(n^2*n^2*2^15)

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=50;
    const int maxm=100;
    const int INF=0x3f3f3f3f;
    int casn,n,m,k;
    char mp[123][123];
    int sx[maxn],sy[maxn],tx[maxn],ty[maxn];
    struct node{
    	int x,y,c;
    };
    bool vis[maxn][maxn];
    int dis[maxn];
    int dd[maxn][maxn];
    int dp[maxn][1<<16];
    const int dir[4][2]={1,0,-1,0,0,1,0,-1};
    #define dx dir[d][0]
    #define dy dir[d][1]
    queue<node>q;
    int bfs(int st,int ed){
    	while(!q.empty())q.pop();
    	memset(dis,0x3f,sizeof dis);
    	memset(vis,0,sizeof vis);
    	q.push((node){tx[st],ty[st],0});
    	while(!q.empty()){
    		node now=q.front();q.pop();
    		if(now.x==sx[ed]&&now.y==sy[ed]){
    			return now.c;
    		}
    		for(int d=0;d<4;d++){
    			int x=now.x+dx;
    			int y=now.y+dy;
    			if(x&&y&&x<=n&&y<=n&&mp[x][y]!='#'&&!vis[x][y]){
    				vis[x][y]=1;
    				q.push((node){x,y,now.c+1});
    			}
    		}
    	}
    	return -1;
    }
    
    int main(){
    //#define test
    #ifdef test
    	freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    #endif
    	while(cin>>n>>m){
    		memset(mp,'#',sizeof mp);
    		for(int i=1;i<=n;i++){
    			scanf("%s",(mp[i]+1));
    		}
    		for(int i=0;i<m;i++){
    			cin>>sx[i]>>sy[i]>>tx[i]>>ty[i];
    		}
    
    		memset(dp,-1,sizeof dp);
    		memset(dd,0x3f,sizeof dd);
    		for(int i=0;i<m;i++)dp[i][1<<i]=0;
    		for(int state=0;state<(1<<m);state++){
    			for(int i=0;i<m;i++){
    				if(state&(1<<i)&&dp[i][state]!=-1){
    					for(int j=0;j<m;j++){
    						if(!((1<<j)&state)&&dd[j][i]!=-1){
    							if(dd[j][i]==INF) dd[j][i]=bfs(j,i);
    							if(dd[j][i]==-1){
    								continue;
    							}
    							int k=state|(1<<j),cost=dp[i][state]+dd[j][i];
    							if(dp[j][k]==-1||dp[j][k]>cost){
    								dp[j][k]=cost;
    							}
    						}
    					}
    				}
    			}
    		}
    		int ans=-1;
    		for(int i=0;i<m;i++){
    			if(dp[i][(1<<m)-1]==-1)continue;
    			if(ans==-1||ans>dp[i][(1<<m)-1]) ans=dp[i][(1<<m)-1];
    		}
    		cout<<ans<<endl;
    	}
    
    #ifdef test
    	fclose(stdin);fclose(stdout);system("out.txt");
    #endif
    	return 0;
    }
    

      

  • 相关阅读:
    8.26 树状数组
    8.27 神异之旅
    8.26 雇佣
    8.28 Jack与Rose
    8.28 ISN
    保存和加载网络
    快速搭建网络
    分类网络
    torch中的回归
    pytorch中的Variable
  • 原文地址:https://www.cnblogs.com/nervendnig/p/8697000.html
Copyright © 2011-2022 走看看