哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级)
A.小乐乐的组合数+:根据等差数列来暴力枚举起点即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 int n,m,a[]={0,6,5,4,3,2,1};LL cnt; 5 int main(){ 6 while(cin>>n>>m){ 7 if(n>m)swap(n,m); 8 cnt=0; 9 for(int i=1;i<=n;++i) 10 cnt+=(m-a[i%7])/7+(i%7>0); 11 cout<<cnt<<endl; 12 } 13 return 0; 14 }
B.小乐乐搭积木:基础状压dp。
递推:
1 #include<iostream> 2 #include<algorithm> 3 #include<string.h> 4 using namespace std; 5 typedef long long LL; 6 const int maxn=15; 7 const LL mod=1e9+7; 8 LL dp[2][1<<11];int n,m; 9 int main(){ 10 while(cin>>n>>m){ 11 if(n*m&1){cout<<0<<endl;continue;} 12 if(n>m)swap(n,m); 13 memset(dp,0,sizeof(dp)); 14 LL *cur=dp[0],*next=dp[1];cur[0]=1; 15 for(int j=0;j<m;++j){ 16 for(int i=0;i<n;++i){ 17 memset(dp[(j*n+i+1)&1],0,sizeof(dp[(j*n+i+1)&1])); 18 cur=dp[(j*n+i)&1],next=dp[(j*n+i+1)&1]; 19 for(int used=0;used<(1<<n);++used){ 20 if((used>>i)&1)next[used&~(1<<i)]+=cur[used];///不需要摆放 21 else{ 22 if(j+1<m)next[used|(1<<i)]+=cur[used];///尝试横着放 23 if(i+1<n&&!((used>>(i+1))&1))next[used|(1<<(i+1))]+=cur[used];///尝试竖着放 24 } 25 } 26 } 27 } 28 cout<<next[0]<<endl; 29 } 30 return 0; 31 }
递归:
1 #include<iostream> 2 #include<algorithm> 3 #include<string.h> 4 using namespace std; 5 typedef long long LL; 6 const int maxn=13; 7 const LL mod=1e9+7; 8 int n,m;LL dp[maxn][1<<11]; 9 void dfs(int j,int i,int state,int nex){ 10 if(i==n){dp[j+1][nex]+=dp[j][state];return;} 11 if(((1<<i)&state)>0) 12 dfs(j,i+1,state,nex); 13 if(((1<<i)&state)==0) 14 dfs(j,i+1,state,nex|(1<<i)); 15 if(i+1<n&&((1<<i)&state)==0&&((1<<(i+1))&state)==0) 16 dfs(j,i+2,state,nex); 17 } 18 int main(){ 19 while(cin>>n>>m){ 20 if(n*m&1){cout<<0<<endl;continue;} 21 if(n>m)swap(n,m); 22 memset(dp,0,sizeof(dp)),dp[1][0]=1; 23 for(int j=1;j<=m;++j) 24 for(int i=0;i<(1<<n);++i) 25 if(dp[j][i])dfs(j,0,i,0); 26 cout<<dp[m+1][0]<<endl; 27 } 28 return 0; 29 }
C.小乐乐玩木桶:短板原理。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 int n,s,x,ans; 5 int main(){ 6 while(cin>>n>>s){ 7 cin>>x,ans=x; 8 while(--n){cin>>x,ans=min(x,ans);} 9 cout<<ans*s<<endl; 10 } 11 return 0; 12 }
D.小乐乐玩木桶+:排序取倒数第三个即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 int n,s,x[1005]; 5 int main(){ 6 while(cin>>n>>s){ 7 for(int i=0;i<n;++i)cin>>x[i]; 8 sort(x,x+n); 9 cout<<x[n-3]*s<<endl; 10 } 11 return 0; 12 }
E.小乐乐匹配字符串:最长公共子序列。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int maxn=1005; 5 char s1[maxn],s2[maxn];int dp[maxn][maxn],ans,len1,len2; 6 int main(){ 7 while(cin>>s1>>s2){ 8 memset(dp,0,sizeof(dp));ans=0,len1=strlen(s1),len2=strlen(s2); 9 for(int i=1;i<=len1;++i){ 10 for(int j=1;j<=len2;++j){ 11 if(s1[i-1]==s2[j-1])dp[i][j]=dp[i-1][j-1]+1; 12 else dp[i][j]=max(dp[i][j-1],dp[i-1][j]); 13 ans=max(ans,dp[i][j]); 14 } 15 } 16 cout<<ans<<endl; 17 } 18 return 0; 19 }
F.小乐乐下象棋:定义dp[k][x][y]表示走k步到坐标(x,y)的方案数。
递推:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int maxn=220; 5 const LL mod=1e9+7; 6 int n,m,k,nx,ny,dir[8][2]={{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};LL dp[2][maxn][maxn]; 7 inline void print(LL x){ 8 if(x<0)putchar('-'),x=-x; 9 if(x>9)print(x/10); 10 putchar(x%10+'0'); 11 } 12 int main(){ 13 while(~scanf("%d%d%d",&n,&m,&k)){ 14 memset(dp,0,sizeof(dp)),dp[0][0][0]=1LL; 15 for(int i=1;i<=k;++i){ 16 memset(dp[i&1],0,sizeof(dp[i&1])); 17 for(int x=0;x<n;++x){ 18 for(int y=0;y<m;++y){ 19 for(int j=0;j<8;++j){ 20 nx=x+dir[j][0],ny=y+dir[j][1]; 21 if(nx>=0&&nx<n&&ny>=0&&ny<m)dp[i&1][nx][ny]=(dp[i&1][nx][ny]+dp[(i-1)&1][x][y])%mod; 22 } 23 } 24 } 25 } 26 print(dp[k&1][n-1][m-1]),puts(""); 27 } 28 return 0; 29 }
递归:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int maxn=220; 5 const LL mod=1e9+7; 6 int n,m,k,nx,ny,dir[8][2]={{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};LL dp[maxn][maxn][maxn]; 7 inline void print(LL x){ 8 if(x<0)putchar('-'),x=-x; 9 if(x>9)print(x/10); 10 putchar(x%10+'0'); 11 } 12 LL dfs(int step,int x,int y){ 13 if(!step&&x==n-1&&y==m-1)return dp[step][x][y]=1; 14 if(step<=0)return 0; 15 if(dp[step][x][y]!=-1)return dp[step][x][y]; 16 LL ans=0; 17 for(int i=0;i<8;++i){ 18 int nx=x+dir[i][0],ny=y+dir[i][1]; 19 if(nx>=0&&nx<n&&ny>=0&&ny<m) 20 ans=(ans+dfs(step-1,nx,ny)%mod)%mod; 21 } 22 return dp[step][x][y]=ans; 23 } 24 int main(){ 25 while(~scanf("%d%d%d",&n,&m,&k)){ 26 memset(dp,-1,sizeof(dp)); 27 print(dfs(k,0,0)),puts(""); 28 } 29 return 0; 30 }
G.小乐乐打游戏
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int maxn=1005; 5 int n,m,dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};char mp[maxn][maxn]; 6 int fx,fy,sx,sy,ex,ey,ans;bool vis[maxn][maxn]; 7 struct node{int x,y,step;}tmp,nod; 8 queue<node> que; 9 int bfs(int x,int y){ 10 while(!que.empty())que.pop(); 11 tmp.x=x,tmp.y=y,tmp.step=0; 12 que.push(tmp),vis[x][y]=true; 13 while(!que.empty()){ 14 nod=que.front(),que.pop(); 15 if(nod.x==ex&&nod.y==ey)return nod.step; 16 for(int i=0;i<4;++i){ 17 int nx=nod.x+dir[i][0],ny=nod.y+dir[i][1]; 18 if(nx>=0&&ny>=0&&nx<n&&ny<m&&!vis[nx][ny]&&mp[nx][ny]!='#'){ 19 vis[nx][ny]=true; 20 tmp.x=nx,tmp.y=ny,tmp.step=nod.step+1; 21 que.push(tmp); 22 } 23 } 24 } 25 return 0; 26 } 27 int main(){ 28 while(cin>>n>>m){ 29 for(int i=0;i<n;++i)cin>>mp[i]; 30 for(int i=0;i<n;++i){ 31 for(int j=0;j<m;++j){ 32 if(mp[i][j]=='S')sx=i,sy=j; 33 else if(mp[i][j]=='F')fx=i,fy=j; 34 else if(mp[i][j]=='E')ex=i,ey=j; 35 } 36 } 37 memset(vis,false,sizeof(vis)); 38 ans=bfs(sx,sy); 39 if(ans&&ans<=abs(fx-ex)+abs(fy-ey))puts("PIG PIG PIG!"); 40 else puts("A! WO SI LA!"); 41 } 42 return 0; 43 }
H.留坑。
I.小乐乐学博弈:只要两堆石子的数量相等,小乐乐就一定会输。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a,b,k; 4 int main(){ 5 while(cin>>a>>b>>k){ 6 if(a==b)puts("LAOZI CHUI SI NI!"); 7 else puts("HAI YOU SEI!"); 8 } 9 return 0; 10 }
J.小乐乐和25:直接bfs模拟。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 int n,bits,m,t0,t1,t2,t3,t4; 5 struct node{int x,step;}nod,tmp; 6 map<int,bool> mp;queue<node> que; 7 int bfs(int x){ 8 while(!que.empty())que.pop(); 9 nod.step=0,mp[nod.x=x]=true,que.push(nod); 10 while(!que.empty()){ 11 nod=que.front(),que.pop(); 12 if(nod.x%25==0)return nod.step; 13 for(int i=10,pos=2;pos<=bits;++pos,i*=10){ 14 if(pos==bits)t0=0; 15 else t0=nod.x/(i*10)*(i*10);///前一位 16 t1=nod.x%i; 17 t2=t1/(i/10); 18 t1-=t2*(i/10);///后两位剩下的数字 19 t2*=i;///后一位 20 t3=nod.x/i%10*(i/10);///当前位 21 t4=t0+t1+t2+t3; 22 if(!mp[t4])mp[t4]=true,tmp.x=t4,tmp.step=nod.step+1,que.push(tmp); 23 } 24 } 25 return -1; 26 } 27 int main(){ 28 while(cin>>n){ 29 m=n,bits=0,mp.clear(); 30 while(m)bits++,m/=10; 31 cout<<bfs(n)<<endl; 32 } 33 return 0; 34 }