训练报告 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;
}

  

posted @ 2018-04-02 20:26  nervending  阅读(408)  评论(0编辑  收藏  举报