NOIP2010提高组题解
T1:机器翻译
题目大意:顺序输入n个数,有一个队列容量为m,遇到未出现元素入队,求入队次数。
AC做法:直接开1000的队列模拟过程。
T2:乌龟棋
题目大意:有长度为n的棋盘,每个格子对应一个分数,1,2,3,4的卡片共m张,给出四种卡片各自的数量,求改变出牌顺序能获得的最大分数。
思路:开了一个四维的f[i][j][k][l]来表示每张牌有了几张时的最大分数;
F[i][j][k][l]=max(f[i-1][j][k][l],f[i][j-1][k][l],f[i][j][k-1][l],f[i][j][k][l-1])+a[i+2*j+3*k+4*l];
#include <iostream> #include <memory.h> using namespace std; int n,m,a[355]; int c[125]; int num[5]; int f[51][51][51][51]; int main() { cin >> n >> m; for (int i=1;i<=n;i++) cin >> a[i]; for (int i=1;i<=m;i++) { cin >> c[i]; num[c[i]]++; } for (int i=0;i<=num[1];i++) for (int j=0;j<=num[2];j++) for (int k=0;k<=num[3];k++) for (int l=0;l<=num[4];l++) { if (i) f[i][j][k][l]=max(f[i][j][k][l],f[i-1][j][k][l]); if (j) f[i][j][k][l]=max(f[i][j][k][l],f[i][j-1][k][l]); if (k) f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k-1][l]); if (l) f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k][l-1]); f[i][j][k][l]+=a[i+2*j+3*k+4*l+1]; } cout << f[num[1]][num[2]][num[3]][num[4]] << "\n"; }
T3:关押罪犯
题目大意:有n个罪犯要分到2个监狱,有的罪犯间结怨,如果怨气值为c就会发生影响为c的冲突。求最大冲突的最小值。
思路:用并查集来表示监狱,将冲突降序排序,冲突大的尽量分开,
直到矛盾,输出矛盾的冲突值即为最大。
#include <iostream> #include <algorithm> using namespace std; int n,m; struct node { int a,b,c; bool operator < (const node &xx) const { return c<xx.c; } }e[100011]; int x[40011]; int find(int ax) { return x[ax]==ax?ax:x[ax]=find(x[ax]); } int main() { cin >> n >> m; for (int i=1;i<=m;i++) cin >> e[i].a >> e[i].b >> e[i].c; sort(e+1,e+m+1); for (int i=1;i<=n*2;i++) x[i]=i; for (int i=m;i>=1;i--) { int fx=find(e[i].a); int fy=find(e[i].b); if (fx==fy) { cout << e[i].c << "\n"; return 0; } x[fy]=find(e[i].a+n); x[fx]=find(e[i].b+n); } cout << 0 << "\n"; }
T4:引水入城
题目大意:有n*m的矩阵城市群。。。(→_→)第一排靠湖,第n排靠沙漠,每个城市海拔不同,沿湖城市可以造蓄水厂向海拔低的城市送水,求第n排能否都送到水。
(关于输出) 能:1 不能:0
(最少蓄水厂数) (无水城市数)
思路:可以先bfs一次,如果最后一行没有全覆盖,顺便输出数量就可以结束了。如果全覆盖了,那么就对每个一线城市进行dfs求出它覆盖的n线城市的连续区间。最后进行区间覆盖。
#include <iostream> #include <queue> #include <cstring> using namespace std; int n,m; int map[501][501]; int num; int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1}; struct ct { int x,y,h; }tc,nw; queue<ct> q; int v[501][501]; struct xd { int l,r; }g[501]; int f[501]; int now; void dfs(int ax,int ay) { v[ax][ay]=1; if (ax==n) { g[now].l = min(g[now].l,ay); g[now].r = max(g[now].r,ay); } for (int i=0;i<4;i++) { int xx=ax+dx[i]; int yy=ay+dy[i]; if (xx>n||xx<1||yy>m||yy<1||map[ax][ay]<=map[xx][yy]) continue; if (!v[xx][yy]) dfs(xx,yy); } } int main() { cin >> n >> m; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) cin >> map[i][j]; for (int i=1;i<=m;i++) { tc.x=1; tc.y=i; tc.h=map[1][i]; q.push(tc); v[1][i]=1; } while (!q.empty()) { nw=q.front(); q.pop(); for (int d=0;d<4;d++) { tc.x=nw.x+dx[d],tc.y=nw.y+dy[d]; if (tc.x<1||tc.x>n||tc.y<1||tc.y>m) continue; tc.h=map[tc.x][tc.y]; if (!v[tc.x][tc.y] && tc.h<nw.h) { q.push(tc); v[tc.x][tc.y]=1; } } } int ans=0; for (int i=1;i<=m;i++) if (!v[n][i]) ans++; if (ans>0) { cout << "0\n"; cout << ans << "\n"; return 0; } cout << "1\n"; for (int i=1;i<=m;i++) { memset(v,0,sizeof(v)); now=i; g[now].l=m+1; g[now].r=0; dfs(1,i); } f[0] = 0; for (int i=1;i<=m;i++) { f[i]=1<<30; for (int j=1;j<=m;j++) if (i>=g[j].l && i<=g[j].r) f[i]=min(f[i],f[g[j].l-1]+1); } cout << f[m] << "\n"; }