练习赛20150412
这套题分别在总结3313~3321
A.
水
B.大模拟,敲了好长时间。。。
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; char str[35][1000] = { "111111MMM11111111MMMMMMMMMMM111111111MMMMMMMM1111MMMMMMMMMMM11111MMMMMMMMMMMM1111MMMMMMMMMMMMM11" ,"11111MM1MM1111111MM11111111MM111111MM1111111MM111MM111111111MM111MM11111111111111MM1111111111111" ,"1111MM111MM111111MM11111111MM11111MM111111111MM11MM1111111111MM11MM11111111111111MM1111111111111" ,"111MMMMMMMMM11111MMMMMMMMMMM111111MM1111111111111MM1111111111MM11MMMMMMMMMMMM1111MMMMMMMMMMMMM11" ,"11MM1111111MM1111MM11111111MM11111MM111111111MM11MM1111111111MM11MM11111111111111MM1111111111111" ,"1MMM11111111MM111MM11111111MM111111MM1111111MM111MM111111111MM111MM11111111111111MM1111111111111" ,"1MM1111111111MM11MMMMMMMMMMM111111111MMMMMMMM1111MMMMMMMMMMM11111MMMMMMMMMMMM1111MM1111111111111" ,"11111MMMMMMMM1111MM111111111MM1111111MMMMMM111111111MMMMMMMM111111MM111111MMM11111MM111111111111" ,"111MM1111111MM111MM111111111MM111111111MM11111111111111MM111111111MM11111MMM111111MM111111111111" ,"11MM111111111MM11MM111111111MM111111111MM11111111111111MM111111111MM111MMM11111111MM111111111111" ,"11MM1111111111111MMMMMMMMMMMMM111111111MM11111111111111MM111111111MMMMM11111111111MM111111111111" ,"11MM111111MMMMM11MM111111111MM111111111MM1111111111MM11MM111111111MM111MMM11111111MM111111111111" ,"111MM1111111MM111MM111111111MM111111111MM1111111111MMM1MM111111111MM11111MMM111111MM111111111111" ,"11111MMMMMMMMM111MM111111111MM1111111MMMMMM1111111111MMMM111111111MM111111MMMM1111MMMMMMMMMMMM11" ,"1MM1111111111MM11MMM111111111MM111111MMMMMM111111MMMMMMMMMMM111111111MMMMMM111111MMMMMMMMMMM1111" ,"1MMMM111111MMMM11MMMM11111111MM1111MMM1111MMM1111MM111111111MM11111MMM1111MMM1111MM111111111MM11" ,"1MM1MM1111MM1MM11MM1MM1111111MM111MMM111111MMM111MM1111111111MM111MMM111111MMM111MM1111111111MM1" ,"1MM11MMMMM111MM11MM11MM111111MM11MM1111111111MM11MM111111111MM111MM1111111111MM11MM111111111MM11" ,"1MM1111M11111MM11MM1111MM1111MM111MMM111111MMM111MMMMMMMMMMM111111MMM1MMMM1MMM111MMMMMMMMMMM1111" ,"1MM1111111111MM11MM111111MMM1MM1111MMM1111MMM1111MM1111111111111111MMM11MMMMM1111MM11111111MM111" ,"1MM1111111111MM11MM11111111MMMM111111MMMMMM111111MM1111111111111111111MMMM1MMMM11MM111111111MMM1" ,"1111MMMMMMMM111111MMMMMMMMMMMM111MM1111111111MM11MMMM111111MMMM11MM1111111111MM111MMM111111MMM11" ,"111MM1111111MM1111MMMMMMMMMMMM111MM1111111111MM111MMM111111MMM111MM1111111111MM1111MMM1111MMM111" ,"11MMM1111111MMM11111111MM11111111MM1111111111MM111MMM111111MMM1111MM111MM111MM111111MMM11MMM1111" ,"1111MMMMM11111111111111MM11111111MM1111111111MM1111MMM1111MMM11111MM111MM111MM11111111MMMM111111" ,"1MMM111MMMM111111111111MM11111111MMM11111111MMM11111MMM11MMM111111MM111MM111MM111111MMM11MMM1111" ,"111MMM11111MMM111111111MM11111111MMM11111111MMM111111MM11MM1111111MM1MM11MM1MM11111MMM1111MMM111" ,"11111MMMMMMM11111111111MM1111111111MMMMMMMMMM111111111MMMM111111111MMM1111MMM11111MMM111111MMM11" ,"11MMM111111MMM11111MMMMMMMMMM111" ,"111MMM1111MMM1111111111111MM1111" ,"1111MMM11MMM1111111111111MM11111" ,"111111MMMM11111111111111MM111111" ,"1111111MM1111111111111MM11111111" ,"1111111MM111111111111MM111111111" ,"1111111MM1111111111MMMMMMMMMMM11" }; int num[30]; //强联通有多少个节点 int weizhi[26][7*16][2]; //第i个字母dfs到的地k各节点与起点的差 int nn; int judge(int x, int y, int x1, int x2, int y1, int y2){ if(x1 <= x && x <= x2 && y1 <= y && y <= y2 && str[x][y] =='M')return 1; return 0; } int move[8][2] = {0, 1, 0, -1, 1, 0, 1, -1, 1, 1, -1, 0, -1, -1, -1, 1}; int vis[305][305], vis1[305][305]; int dfs(int x, int y, int sx, int sy, int x1, int x2, int y1, int y2){//printf("%d %d %d %d %d %d %d %d\n", x, y, sx, sy,x1,x2,y1,y2); if(vis[x][y])return 0; vis[x][y] = 1; weizhi[nn][num[nn]][0] = sx-x; weizhi[nn][num[nn]++][1] = sy-y; /*if(nn == 'u'-'a'){ printf("**%d %d %d %d\n", weizhi['u'-'a'][num[nn]-1][0], weizhi['u'-'a'][num[nn]-1][1], sx-x, sy-y); }*/ for(int i = 0; i < 8; i++){ if(judge(x+move[i][0], y+move[i][1],x1,x2, y1, y2)){//printf("**%d %d %d %d %d %d %d %d\n", x+move[i][0], y+move[i][1], sx, sy,x1,x2,y1,y2); dfs(x+move[i][0], y+move[i][1], sx, sy,x1,x2, y1, y2); } } } char str1[305][305]; int judge1(int x, int y, int n, int m){ if(0 <= x && x < n && 0 <= y && y < m && str1[x][y] == 'M') return 1; return 0; } int nnu, dp; void dfs1(int x, int y, int n, int m, int sx, int sy){//printf("%d %d %d %d\n", x, y, sx, sy); if(vis1[x][y])return; vis1[x][y] = 1; if(nnu < 7*17){ //printf("**%d %d ", weizhi['u'-'a'][nnu][0], weizhi['u'-'a'][nnu][1]); //printf("%d ", dp); int s= 0; int xx = sx - x, yy = sy - y; for(int i = 0; i < 26; i++){ if(weizhi[i][nnu][0] == xx && weizhi[i][nnu][1] == yy){ s |= (1<<i); } }//printf("--%d--", s); dp &= s; //printf("%d %d %d %d\n", sx-x,sy-y, dp, s); nnu++; }else dp = 0; for(int i = 0; i < 8; i++){ if(judge1(x+move[i][0], y+move[i][1], n, m)){ dfs1(x+move[i][0], y+move[i][1], n, m, sx, sy); } } } int ans[30]; int Ans(int n, int m){ memset(vis1, 0, sizeof(vis1));; for(int i = 0; i < n; i++){ for(int k = 0; k < m; k++){ if(vis1[i][k] || str1[i][k]!='M')continue; nnu = 0; dp = (1<<26)-1; dfs1(i, k, n, m, i, k);//printf("**%d\n", dp); for(int j = 0; j < 26; j++){ if(((1<<j) & dp) && nnu == num[j]){ ans[j] = 1; } } } } } char ss[305][305]; int main(){ for(int i =0; i < 35; i+= 7){ for(int k = 0; k < 96; k+=16){ int x1 = i,x2 = i+6, y1 = k, y2 = k+16; for(int ii = i; ii < i+7; ii++){ for(int kk = k; kk < k +16; kk++){ if(vis[ii][kk])continue; if(str[ii][kk] == 'M'){//printf("%d %d\n", ii, kk); dfs( ii, kk, ii, kk,x1,x2,y1,y2); } } } nn++; if(nn == 26)break; } } int n, m; while(scanf("%d%d", &n, &m)!=EOF){ memset(ans, 0, sizeof(ans)); for(int i = 0;i < n; i++){ scanf("%s", str1[i]); } //Ans(n, m); for(int u = 0; u < 4; u++){ Ans(n, m); for(int i = 0;i < m; i++){ for(int k = 0; k < n ;k++){ ss[i][k] = str1[n-1-k][i]; } }swap(n, m); for(int i =0 ; i <n;i++){ for(int k = 0; k < m ; k++){ str1[i][k] = ss[i][k]; } } } for(int i = 0;i < 26; i++){ if(ans[i])printf("%c", 'A'+i); }puts(""); } }
C.
D.
E.简单模拟题,又wa了好多次,当时脑子坏掉
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int maxa = 105; struct point{ int in, out, id; }p[maxa]; int cmp(point a, point b){ return a.in < b.in; } int room[maxa], liveroom[maxa];; int ans[maxa]; int main(){ int n, m; while(scanf("%d%d", &n, &m)!=EOF){ if(n == 0 && m == 0)return 0; for(int i = 1; i <= n; i++){ scanf("%d%d", &p[i].in, &p[i].out); p[i].id = i; } sort(p+1, p+n+1, cmp); memset(room, 0, sizeof(room)); memset(liveroom, 0, sizeof(liveroom)); memset(ans, 0, sizeof(ans)); for(int i = 1;i <= n; i++){ for(int k = 1; k <= m; k++){ if(liveroom[k] <= p[i].in){ liveroom[k] = p[i].out; ans[p[i].id] = k; liveroom[k] = p[i].out; break; } } } for(int i =1 ; i<= n; i++){ printf("%d\n", ans[i]); } } }
F.有m张地图,有一个起点s和一个终点t,一条路径的价值是s到t的距离+与上一路径相同?0:1.
由于只有三十条路径所以可以将所有图压缩到一个图上,点也不多,dp[i] = dp[j]+bfs(j+1,i),bfs(j+1,i)指的是j+1到i路径相同所产生的值,广搜可以做到。
ps:(可能如果有更多的时间能想到,但是当时状态不好加敲打模拟用去大量时间。。。。。)
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> using namespace std; const int maxa = 35; int edge[maxa][maxa]; int n, m, s, t; int vis[maxa]; int dp[maxa]; int bfs(int ii, int kk){ memset(vis, -1, sizeof(vis)); vis[s] = 0; queue<int> Q; Q.push(s);//puts(""); while(!Q.empty()){ int now = Q.front(); Q.pop();//printf("**%d\n", now); if(now == t) break; for(int i = 0 ; i < n; i++){ int ok = 1; if(vis[i] != -1)continue; for(int k = ii; k <= kk; k++){ //printf("%d %d %d\n", edge[now][i], now, i); if((edge[now][i] & (1<<k)) == 0){ ok =0; break; } } if(ok){ vis[i] = vis[now]+1; Q.push(i); } } }//printf("--%d %d %d\n",ii, kk, vis[t]); if(vis[t] == -1)return 100000; if(ii == 0)return (kk-ii+1)*vis[t]; return (kk-ii+1)*vis[t]+1; } int main(){ int T; scanf("%d", &T); while(T--){ scanf("%d%d%d%d", &n, &m, &s, &t); s--,t--; memset(edge, 0, sizeof(edge)); for(int i = 0; i < m; i++){ int r; scanf("%d", &r); while(r--){ int x, y; scanf("%d%d", &x, &y);x--,y--; edge[x][y] |= (1<<i); edge[y][x] |= (1<<i); } }//bfs(0, 0); for(int i =0 ;i < m; i++)dp[i] = 1000000; for(int i = 0;i < m; i++){ for(int k = 0;k <= i; k++){ if(k == 0){ dp[i] = min(dp[i],bfs(k, i)); }else{ dp[i] = min(dp[i], dp[k-1]+bfs(k, i)); } } } /*for(int i = 0;i < m; i++){ printf("*%d\n", dp[i]); }*/ printf("%d\n", dp[m-1]); } }
G.错排公式,错排公式是让n个点每个点都不在原来的位置,有多少中排列情况。d[i] = (n-1)*(d[i-1]+d[i-2]),很常用的一个公式,然后只要枚举有多少个链形成自环其他错排,有种情况就是有自环或者有环但是有零个点错排,这样加一。
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int maxa = 105; int rudu[maxa], chudu[maxa]; char str[maxa][maxa]; int dp[maxa]; const int mod = 10000007; long long c[maxa][maxa]; void table() { int i,j; for(i=0;i<maxa;i++) { for(j=0;j<=i;j++) { if(!j||i==j) c[i][j]=1; else c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod; } } return; } int next[maxa]; int main(){ table(); dp[2] = 1; for(int i = 3; i < maxa; i++){ dp[i] = (i-1)*(dp[i-1]+dp[i-2]); dp[i] %= mod; } dp[0] = 0; int n; while(scanf("%d", &n), n){ for(int i = 0; i < n; i++){ next[i] = -1; } memset(rudu, 0, sizeof(rudu)); memset(chudu, 0, sizeof(chudu)); for(int i =0;i < n; i++){ scanf("%s", &str[i]); } for(int i = 0;i < n; i++){ for(int k =0;k < n; k++){ if(str[i][k] == 'Y'){ rudu[i] ++; chudu[k] ++; next[i] = k; } } } int ok = 1; int nn = 0; int mm = 0; for(int i =0;i < n; i++){ if(rudu[i] > 1 || chudu[i] > 1){ ok =0; } if(rudu[i] == 0){ nn ++; if(chudu[i] != 0)mm++; } } if(ok == 0){ printf("0\n"); }else{ int huan = 0; for(int i =0 ;i < n; i++){ int ii = next[i]; while(ii != -1){ if(ii == i){ huan = 1; break; } ii = next[ii]; } } int ans = 0; for(int i = 0; i <= mm; i++){ if((huan || i > 0)&&(nn-i)==0){//printf("*"); ans ++; } ans += int((c[mm][i]*dp[nn-i])%mod); ans %= mod; } printf("%d\n", ans); } } } /* 5 NYNNN NNNNN NNNYN YNNNN NNNNN */