2014上海全国邀请赛题解 HDOJ 5090-5099
HDOJ 5090
水题。从小到大排序,能够填充达到符合条件的。先填充好。填充之后进行调整。
传送门:点击打开链接
#include <cstdio> #include <cmath> #include <queue> #include <map> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1e2+10; int t, n, k, ia[MAXN]; int main() { scanf("%d", &t); while(t--) { scanf("%d%d", &n, &k); bool flag = true; for(int i=1; i<=n; ++i) { scanf("%d", ia+i); } sort(ia+1, ia+n+1); for(int i=1; i<=n; ++i) { if(i < ia[i]) { flag = false; break; } if(i == ia[i]) { continue; } if(0 == (i-ia[i])%k) { ia[i] = i; } else { int tp = 1; for(int j=i+1; j<=n; ++j) { if(0 == (j-ia[i])%k) { ia[i] = j; tp = 0; --i; break; } } if(tp) { flag = false; break; } } sort(ia+1, ia+n+1); } printf("%s\n", flag ?"Jerry" : "Tom"); } return 0; }
HDOJ 5092
题意:每行取一个数。使总和最小,取了mp[i][j]之后,仅仅能在该点左下,正下。右下三个位置里面取下一个点。记录路径。要注意尽量靠右。
分析:一个典型的dp
传送门:点击打开链接
#include <cstdio> #include <cmath> #include <queue> #include <map> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1e2+10; const int INF = 0x7fffffff; int t, m, n, dp[MAXN][MAXN]; int s[MAXN][MAXN], mp[MAXN][MAXN], icase = 1; void output(int i, int j) { if(0 == i) { return ; } if(1 == s[i][j]) { output(i-1, j-1); printf("%d ", j-1); } else if(2 == s[i][j]) { output(i-1, j); printf("%d ", j); } else if(3 == s[i][j]) { output(i-1, j+1); printf("%d ", j+1); } } int main() { scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); memset(dp, 0, sizeof(dp)); memset(mp, 0, sizeof(mp)); memset(s, 0, sizeof(s)); for(int i=1; i<=n; ++i) { for(int j=1; j<=m; ++j) { scanf("%d", &mp[i][j]); } } for(int i=1; i<=m; ++i) { dp[1][i] = mp[1][i]; } for(int i=2; i<=n; ++i) { for(int j=1; j<=m; ++j) { int mn = INF; if(j>=2 && dp[i-1][j-1] <= mn) { mn = dp[i-1][j-1]; s[i][j] = 1; } if(dp[i-1][j] <= mn) { mn = dp[i-1][j]; s[i][j] = 2; } if(j<=m-1 && dp[i-1][j+1] <= mn) { mn = dp[i-1][j+1]; s[i][j] = 3; } dp[i][j] = mn + mp[i][j]; } } int mn = INF, id = 0; for(int i=1; i<=m; ++i) { if(dp[n][i] <= mn) { mn = dp[n][i]; id = i; } } /* printf("%d\n", mn); for(int i=1; i<=n; ++i) { for(int j=1; j<=m; ++j) { printf("%d ", dp[i][j]); } printf("\n"); } */ printf("Case %d\n", icase++); output(n, id); printf("%d\n", id); } return 0; }
HDOJ 5093
分析:二分图。
队友写的,没细看,贴个队友的代码。之后有空再看。
传送门:点击打开链接
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int match[1260]; char map[60][60]; int pic[1260][60]; int vis[1260]; int m,n; int nx=0,ny[60],nk=0,flag=0,yvis[60]; int dp(int now) { int i; for(i=0;pic[now][i]!=-1;i++) { int t=pic[now][i]; if(vis[t]==1) continue; vis[t]=1; if(match[t]==-1||dp(match[t])) { match[t]=now; return 1; } } return 0; } int main() { //freopen("D:\\in.txt","r",stdin); int t,i,j; cin>>t; while(t--) { cin>>m>>n; for(i=0;i<m;i++) scanf("%s",map[i]); memset(yvis,0,sizeof(yvis)); for(i=0;i<n;i++) ny[i]=i; nx=nk=0; flag=0; memset(pic,-1,sizeof(pic)); for(i=0;i<m;i++) { for(j=0;j<n;j++) { if(map[i][j]=='*') { yvis[j]=1; pic[nx][flag++]=ny[j]; } if(map[i][j]=='#') { if(flag) { nx++; flag=0; } if(yvis[j]) { ny[j]=n+nk; nk++; yvis[j]=0; } } } if(flag) { nx++; flag=0; } } int ans=0; memset(match,-1,sizeof(match)); for(i=0;i<=nx;i++) { memset(vis,0,sizeof(vis)); if(dp(i)) ans++; } cout<<ans<<endl; } }
HDOJ 5094
分析:BFS+状压(不然会MLE)。wa点:一个位置可能有几把不同的钥匙。
传送门:点击打开链接
#include <cstdio> #include <cmath> #include <queue> #include <map> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 55; int n, m, p, k, s, mk[MAXN][MAXN]; int vis[1<<11][MAXN][MAXN]; int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; struct P { int x, y, time, key; }; map<int, int> mp; int BFS() { memset(vis, 0, sizeof(vis)); queue<P> que; P s; s.x = s.y = 1; s.key = s.time = 0; if(mk[s.x][s.y]) { s.key = mk[s.x][s.y]; } vis[s.key][s.x][s.y] = 1; que.push(s); while(!que.empty()) { P u = que.front(); que.pop(); if(u.x==n && u.y==m) { return u.time; } for(int i=0; i<4; ++i) { P v; v.x = u.x + dir[i][0]; v.y = u.y + dir[i][1]; if(v.x<1 || v.x>n || v.y<1 || v.y>m) { continue; } int q = 51*51*51*u.x + 51*51*u.y + 51*v.x + v.y; int tp = mp[q]; if(4e8 == tp) { continue; } if(0 == tp) { v.time = u.time + 1; v.key = u.key; if(mk[v.x][v.y] && 0==(mk[v.x][v.y]&u.key)) { v.key += mk[v.x][v.y]; } if(vis[v.key][v.x][v.y]) { continue; } vis[v.key][v.x][v.y] = 1; que.push(v); } else { if(u.key & (1<<tp)) { v.time = u.time + 1; v.key = u.key; if(mk[v.x][v.y] && 0==(mk[v.x][v.y]&u.key)) { v.key += mk[v.x][v.y]; } if(vis[v.key][v.x][v.y]) { continue; } vis[v.key][v.x][v.y] = 1; que.push(v); } } // printf("%d %d %d %d\n", v.x, v.y, v.time, v.key); } } return -1; } int main() { while(~scanf("%d%d%d", &n, &m, &p)) { scanf("%d", &k); mp.clear(); memset(mk, 0, sizeof(mk)); while(k--) { int ux, uy, vx, vy, g, hx, hy; scanf("%d%d%d%d%d", &ux, &uy, &vx, &vy, &g); hx = 51*51*51*ux + 51*51*uy + 51*vx + vy; hy = 51*51*51*vx + 51*51*vy + 51*ux + uy; if(0 == g) g = 4e8; mp[hx] = mp[hy] = g; } scanf("%d", &s); while(s--) { int x, y, q; scanf("%d%d%d", &x, &y, &q); mk[x][y] += (1<<q); } printf("%d\n", BFS()); } return 0; }
HDOJ 5095
分析:水题,写的时候注意处理-1,0。1就差点儿相同了。还有首位为正。不须要+。
传送门:点击打开链接
代码:
#include <cstdio> #include <cmath> #include <queue> #include <map> #include <vector> #include <cstring> #include <algorithm> using namespace std; typedef long long lint; const int MAXN = 20; char ch[] = {'p', 'q', 'r', 'u', 'v', 'w', 'x', 'y', 'z'}; int ia[MAXN], t; int main() { scanf("%d", &t); while(t--) { for(int i=0; i<10; ++i) { scanf("%d", ia+i); } int first = 1, zero = 1; for(int i=0; i<10; ++i) { if(0 == ia[i]) { continue; } zero = 0; if(ia[i] < 0) { if(-1 == ia[i]) { if(i < 9) { printf("-"); } else { printf("-1"); } } else { printf("%d", ia[i]); } first = 0; } else { if(1 == ia[i]) { if(!first) { printf("+"); } first = 0; if(i == 9) { printf("1"); } } else { if(!first) { printf("+"); } first = 0; printf("%d", ia[i]); } } if(i < 9) { printf("%c", ch[i]); } } if(zero) printf("0"); printf("\n"); } return 0; }
HDOJ 5098
队友写的,贴个代码。之后补。
传送门:点击打开链接
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<algorithm> using namespace std; char info[1010][1030]; int need[1010][1010],nn[1010]; int num[1010]; int res[1010],ns; //ns为软件数量,res表示是否要重新启动 map<string,int> list; int dfs(int now) { if(num[now]!=-1) return num[now]; int ma=0,i; for(i=0;need[now][i]!=-1;i++) { int t=need[now][i]; if(res[t]) ma=max(ma,dfs(t)+1); else ma=max(ma,dfs(t)); } num[now]=ma; return num[now]; } int main() { //freopen("D:\\in.txt","r",stdin); int t,i,j,count=1; cin>>t; getchar(); getchar(); while(t--) { memset(info,0,sizeof(info)); list.clear(); memset(res,0,sizeof(res)); i=0; while(gets(info[i])) //開始数据处理 { if(strlen(info[i])==0) break; j=0; while(info[i][j]!='*'&&info[i][j]!=':') j++; list[string(info[i],j)]=i; if(info[i][j]=='*') res[i]=1; i++; } ns=i; memset(need,-1,sizeof(need)); memset(nn,0,sizeof(nn)); for(i=0;i<ns;i++) { int s=0; while(info[i][s]!=' '&&s!=strlen(info[i])) s++; int e=s; while(e!=strlen(info[i])) { s=e; e++; while(e!=strlen(info[i])&&info[i][e]!=' ') e++; need[i][nn[i]++]=list[string(info[i]+s+1,e-s-1)]; } } //数据处理结束。need[i]表示i的依赖包,到-1结束 memset(num,-1,sizeof(num)); int ma=0; for(i=0;i<ns;i++) { if(res[i]) ma=max(ma,dfs(i)+1); else ma=max(ma,dfs(i)); } printf("Case %d: %d\n",count++,ma); } }
HDOJ 5099
分析:水题,字符串比較。
传送门:点击打开链接
代码:
#include <cstdio> #include <cmath> #include <queue> #include <map> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 2e3+10; char cha[MAXN], chb[MAXN]; int t, icase = 1; int main() { scanf("%d", &t); while(t--) { scanf("%s%s", cha, chb); // puts(cha); puts(chb); printf("Case %d: ", icase++); if(cha[0] > chb[0]) { printf("> "); } else if(cha[0] < chb[0]) { printf("< "); } else { printf("= "); } if(cha[1] != chb[1]) { cha[5] = chb[5] = '\0'; } int ret = strcmp(cha+2, chb+2); if(ret > 0) { printf(">"); } else if(ret < 0) { printf("<"); } else { printf("="); } printf("\n"); } return 0; }