AcWing 第13場周賽
阿新 • • 發佈:2021-08-22
排列
生成一種排列,但排列不能升序,這裡提供一種解法,
第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; }