1. 程式人生 > 其它 >AcWing 第13場周賽

AcWing 第13場周賽

排列

生成一種排列,但排列不能升序,這裡提供一種解法,

第n位為1,其餘為i+1

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;
int n;const int maxn=1e3+10;
int t;
int a[maxn];
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;++i){
			if(i!=n)cout<<i+1<<" ";
			else cout<<"1"<<endl;
		}
	}return 0;
}

機器人走迷宮

像走迷宮,先把上下左右走的操作表示出來

現在,哪個數字(0∼3)對應哪種行動(上下左右)還未分配。

即要求我們把它分配了,再按照指令走

分配就可以考慮用全排列,把上下左右按照去全排列的數字分配

上 下 左 右
上 左 下 右
.......
右 左 下 上

每個都試一遍,能到達的,++ans

注意不能走出界和路上遇到障礙

 #include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;
string s;
int n,m;
int t;const int maxn=1e3; 
int nx[5],ny[5];
int tx[5]={1,-1,0,0},ty[5]={0,0,1,-1};//表示上下左右
bool mp[maxn][maxn];
int ans=0;
int pl[5],book[5];
int sx,sy,ex,ey;
void dfs(int len){
	if(len==4){//排列完畢
		for(int i=0;i<len;++i){//分配操作
			nx[i]=tx[pl[i]];
			ny[i]=ty[pl[i]];
		}	
		int xt=sx,yt=sy;
		int lens=s.length();
		for(int i=0;i<lens;++i){//按照指令
			xt+=nx[s[i]-'0'];
			yt+=ny[s[i]-'0'];
			if(mp[xt][yt]) return ;//遇到障礙
			if(yt<1 || xt<1 || xt>n || yt>m) return ;//出界
			if(xt==ex && yt==ey){//達到終點
				++ans;return ;
			}
		}
		return ;
	}
	for(int i=0;i<4;++i){//全排列
		if(book[i]) continue;
		book[i]=1;pl[len]=i;
		dfs(len+1);
		book[i]=0;
	} 
}
int main(){
	cin>>t;
	while(t--){ans=0;
		cin>>n>>m; memset(mp,0,sizeof(mp));
		for(int i=1;i<=n;++i) 
			for(int j=1;j<=m;++j){
				char c;cin>>c;
				if(c=='#') mp[i][j]=1; 
				if(c=='S') sx=i,sy=j;//記錄起點
				if(c=='E') ex=i,ey=j;//記錄終點
			}
		cin>>s;
		dfs(0);
		cout<<ans<<endl;
	}	return 0;
}

最大路徑權值

第一步

如果有環,那麼環上的字母就會無限出現,那麼權值將會無窮大

所以第一步先判斷有沒有,注意是有向圖,所以可以考慮用拓撲排序

第二步

根據題中給的要求,出現頻率最高的字母

注意是字母!像遇到二進位制和字母,都可以嘗試列舉(一般出題人都不會卡你

我們把每個字母列舉,然後求出現列舉的這個字母的最大路權值即可

列舉時,我們把列舉的字母的點的權值設為1,其他為0

根據前面拓撲排序後,沒有環,所以可以用dp
(為什麼可以用,因為是有向圖且沒有環,天然滿足dp的無後效性原則)

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;
int n,m;
const int maxn=3e5+10;
int head[maxn];
int f[maxn];
struct node{
	int v,next;
}e[maxn];
string s;
int cnt=0;
void add(int u,int v){
	e[++cnt].v=v;
	e[cnt].next=head[u];
	head[u]=cnt;
}
int q[maxn];
int in[maxn];//入度
bool topsort(){
	int l=1,r=0;
	for(int i=1;i<=n;++i) if(in[i]==0) q[++r]=i;
	while(l<=r){
		int u=q[l];
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].v;in[v]--;
			if(in[v]==0) q[++r]=v;
		}++l;
	}
	if(r==n) return 0;
	return 1;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>m;
	cin>>s;
	for(int i=1;i<=m;++i){
		int u,v;cin>>u>>v;
		add(u,v);++in[v];
	}
	int res=0;
	if(topsort()) puts("-1");//有環圖 
	else {
	      for(char c='a';c<='z';++c){
		  for(int i=1;i<=n;++i)//初始化 
		       	if(in[i]==0) f[i]=s[i-1]==c;
	
	      	for(int i=1;i<=n;++i){//從前往後dp
			int u=q[i];
			for(int j=head[u];j;j=e[j].next){
				int v=e[j].v;
                                int w=s[v-1]==c;
				f[v]=max(f[v],w+f[u]);
				res=max(res,f[v]);
			}
	  	}
	  }
	  cout<<res<<endl;
        }
	return 0; 
}