P1:n*m的矩形上有若干个单位矩形禁止通行,现在可以整行或者整列的走(不可转向,从头走到尾),问最多可经过多少个单位矩形,重复经过只统计一次。
直接暴力搞之...横刷一遍竖刷一遍输出即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <string> #include <memory.h> using namespace std; char s[20][20]; int n,m; int r[20],c[20]; int rr,cc; int main() { cin>>n>>m; rr=0; cc=0; memset(r,0,sizeof r); memset(c,0,sizeof c); int ans=0; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) cin>>s[i][j]; for (int i=1; i<=n; i++) { int p=0; for (int j=1; j<=m; j++) if (s[i][j]=='S') { r[i]=-1; break; } else p++; if (r[i]!=-1) {r[i]=p; ans+=p; rr++; } } for (int i=1; i<=m; i++) { int p=0; for (int j=1; j<=n; j++) if (s[j][i]=='S') { c[i]=-1; break; } else p++; if (c[i]!=-1) { c[i]=p; ans+=p; cc++; } } ans-=(rr*cc); cout<<ans<<endl; return 0; }
P2:一个国家有n个城市,初始状态下各城市之间独立无道路连接,现在给出k条禁令,每条禁令包涵a,b表示a,b之间不允许有道路,现在问在不违反禁令的情况下,最少建造几条道路,可以满足这个国家中任意两个城市在经过不超过两条路的情况下可达,并输出任意一种方案。
注意到k<n/2,因为完全图中,n个节点共有n(n-1)/2,在k最大的情况下,仍然至少会有一个节点度数为n-1,即这个节点连向其他所有点(菊花链......),所以,只要找到这个节点,输出它和其他n-1个节点连接的道路即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <memory.h> #include <string> #include <cstring> using namespace std; int n,m; int d[1100]; int p,q; int main() { cin>>n>>m; for (int i=1; i<=n; i++) d[i]=n-1; for (int i=1; i<=m; i++) { cin>>p>>q; d[p]--; d[q]--; } int tp=0; for (int i=1; i<=n; i++) if (d[i]==n-1) { tp=i; break; } cout<<n-1<<endl; for (int i=1; i<=n; i++) if (i!=tp) { cout<<tp<<" "<<i<<endl; } return 0; }
P3:一个n*n区域被邪气污染,其中若干个单位区域被恶魔占据,主角无法到达(即使恶魔被净化也无法到达)。主角可以在x,y释放魔法,净化x行和y列的所有区域。现在问主角最少施放多少次魔法可以净化整片区域,同一点可以重复净化,不能净化整个区域时输出-1.
看似和麻烦,事实上如果区域可净化,只可能是每行释放一次魔法,或者是在每一列施放魔法。即设一个集合表示行数,若第i行存在一点可释放魔法,即将i加入集合,同样设另一个集合表示列数,只要行集合包涵1---n或者是列集合包涵1---n即可净化,任意输出一中方案即可,否则输出-1;
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <algorithm> #include <memory.h> using namespace std; char s[200][200]; int r[200],c[200]; int n,m; int main() { cin>>n; for (int i=1; i<=n; i++) for (int j=1; j<=n; j++) cin>>s[i][j]; int ct=0; for (int i=1; i<=n; i++) { for (int j=1; j<=n; j++) if (s[i][j]=='.') { ct++; r[i]=j; break; } } if (ct==n) { for (int i=1; i<=n; i++) cout<<i<<" "<<r[i]<<endl; return 0; } else { ct=0; for (int i=1; i<=n; i++) { for (int j=1; j<=n; j++) if (s[j][i]=='.') { ct++; c[i]=j; break; } } } if (ct==n) { for (int i=1; i<=n; i++) cout<<c[i]<<" "<<i<<endl; } else { cout<<"-1"<<endl; return 0; } return 0; }
P4:喜闻乐见迷宫题,题意转化下来就是迷宫中有一些小队,每个小队有若干人,他们会自行移动。主人公同样也在向出口移动,在路上或者是是出口可能会遇到其他人,现在问主人公最少在遇到多少人的情况下可以走出迷宫。
不难想到,若小队a距出口的距离小于等于主人公距出口的距离,小队a一定可一追到主人公,所以只要以出口为起点,做一个bfs记录下出口到各点的距离,之后统计人数即可。需要注意的一点是有些区域可能会被障碍物个离开,初始化的时候要将所有区域到出口的距离设为无穷大,不然在统计时可能会把隔了区的小队人数也统计进去。
#include <iostream> #include <cstdio> #include <algorithm> #include <memory.h> #include <queue> #include <string> #include <cstring> int n,m; char s[1100][1100]; struct node { int num,x,y; }t[1200000]; const int fx[5]={0,0,1,0,-1}; const int fy[5]={0,1,0,-1,0}; int dis[1100][1100]; bool f[1100][1100]; struct mp { int x,y; int dis; }; node st,ed; using namespace std; int main() { // freopen("a.in","r",stdin); for (int i=0; i<=1010; i++) for (int j=0; j<=1010; j++) dis[i][j]=9999999; memset(f,true,sizeof f); cin>>n>>m; int sp=0; for (int i=1; i<=n; i++) for (int j=1; j<=m; j++) { cin>>s[i][j]; if (s[i][j]=='S') { st.x=i; st.y=j; } if (s[i][j]>='0' && s[i][j]<='9') { sp++; t[sp].x=i; t[sp].y=j; t[sp].num=s[i][j]-'0'; } if (s[i][j]=='E') { ed.x=i; ed.y=j; } } queue<mp> q; mp ss; ss.dis=0; ss.x=ed.x; ss.y=ed.y; q.push(ss); while (!q.empty()) { mp tt=q.front(); mp tp; for (int j=1; j<=4; j++) { tp.x=tt.x+fx[j]; tp.y=tt.y+fy[j]; if (tp.x>0 && tp.y>0 && tp.x<=n && tp.y<=m && s[tp.x][tp.y]!='T' && f[tp.x][tp.y]) { tp.dis=tt.dis+1; f[tp.x][tp.y]=false; q.push(tp); dis[tp.x][tp.y]=tp.dis; } } q.pop(); } int ans=0; for (int i=1; i<=sp; i++) if (dis[t[i].x][t[i].y]<=dis[st.x][st.y]) ans+=t[i].num; cout<<ans<<endl; return 0; }
p5:..还没看,待填坑......