补中档题(难题不考虑)是不可能补了,前面的还没做完,后面的就来了,还压根不会,只能写写水题,练练英语,压压惊咯。
-------窃.尼古拉斯致远
解题思路:
水题,求最小的花费。
代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int main() { int n,m; while(~scanf("%d%d",&n,&m) && n && m){ int ans = 0x3ffffff; ans = min(ans,n*30+m*40); ans = min(ans,n*35+m*30); ans = min(ans,n*40+m*20); printf("%d\n",ans); } return 0; } /********************************************************************** Problem: 2027 User: zhiyuanjiang Language: C++ Result: AC Time:4 ms Memory:2024 kb **********************************************************************/
解题思路:
水题,根据规则判断一个号码是否有效,题目读了好几遍,果然英语战五渣。
扫描二维码关注公众号,回复:
1024050 查看本文章
代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> using namespace std; typedef long long llt; int main() { string str,s1,s2,s3,s4; while(1){ cin >> s1 >> s2 >> s3 >> s4; if(s1 == "0000" && s2 == "0000" && s3 == "0000" && s4 == "0000") break; str = s1+s2+s3+s4; llt ans = 0; for(int i = 0; i < str.length(); i += 2){ int t = str[i]-'0'; t *= 2; if(t > 9) t -= 9; ans += t; } for(int i = 1; i < str.length(); i += 2){ ans += str[i]-'0'; } if(ans%10 == 0) printf("Yes\n"); else printf("No\n"); } return 0; }
解题思路:
广搜,火先蔓延。
代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> #include <queue> using namespace std; typedef long long llt; const int N = 1010; struct Node{ int x,y,dis; Node(int _x,int _y,int _d){ x = _x; y = _y; dis = _d; } }; int r,c,t; int dx[] = {0,0,1,-1,1,-1,1,-1}; int dy[] = {1,-1,0,0,1,-1,-1,1}; char graph[N][N]; vector<Node>p1,p2,f1,f2; bool inside(int x,int y) { return x >= 0 && x < r && y >= 0 && y < c; } int bfs() { p1.clear(); p2.clear(); f1.clear(); f2.clear(); int ex,ey,cnt = 0; for(int i = 0; i < r; ++i){ for(int j = 0; j < c; ++j){ if(graph[i][j] == 'f') f1.push_back(Node(i,j,0)); if(graph[i][j] == 's') p1.push_back(Node(i,j,0)); if(graph[i][j] == 't') ex = i,ey = j; } } while(!p1.empty()){ ++cnt; if(cnt == t){ for(int i = 0; i < f1.size(); ++i){ Node u = f1[i]; for(int j = 0; j < 8; ++j){ int nx = u.x+dx[j]; int ny = u.y+dy[j]; if(inside(nx,ny) && graph[nx][ny] != 'f'){ graph[nx][ny] = 'f'; f2.push_back(Node(nx,ny,0)); } } } f1.clear(); for(int i = 0; i < f2.size(); ++i) f1.push_back(f2[i]); f2.clear(); cnt = 0; } if(graph[ex][ey] == 'f') return 0; for(int i = 0; i < p1.size(); ++i){ Node u = p1[i]; for(int j = 0; j < 4; ++j){ int nx = u.x+dx[j]; int ny = u.y+dy[j]; if(inside(nx,ny) && graph[nx][ny] != 'f' && graph[nx][ny] != '#'){ graph[nx][ny] = '#'; if(nx == ex && ny == ey) return u.dis+1; p2.push_back(Node(nx,ny,u.dis+1)); } } } p1.clear(); for(int i = 0; i < p2.size(); ++i) p1.push_back(p2[i]); p2.clear(); } return 0; } int main() { while(~scanf("%d%d%d",&r,&c,&t) && r && c && t){ for(int i = 0; i < r; ++i) scanf(" %s",graph[i]); int ans = bfs(); if(ans) printf("%d\n",ans); else printf("Impossible\n"); } return 0; }
解题思路:
dp,最长上升子序列。
代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> #include <queue> using namespace std; typedef long long llt; const int N = 1010; string sa,sb,sc; int f[N],dp[N],d[N]; int toInt(char ch) { return ch-'0'; } int main() { // freopen("d:\\h.in","r",stdin); // freopen("d:\\out.txt","w",stdout); int n; while(~scanf("%d",&n) && n){ cin >> sa >> sb >> sc; memset(dp,0,sizeof(dp)); memset(f,0,sizeof(f)); memset(d,0,sizeof(d)); int temp,ans = 0; for(int i = n-1; i >= 0; --i){ for(int j = i+1; j <= n; ++j){ temp = (toInt(sa[i])+toInt(sb[i])+f[j]); if(temp%10 == toInt(sc[i])){ if(dp[i] < dp[j]+1) dp[i] = dp[j]+1,f[i] = temp/10; } if(temp == toInt(sc[i])) ans = max(ans,dp[j]+1); } } printf("%d\n",n-ans); } return 0; }
解题思路:
给定一个01串S,然后给你S的子串t,问t修改最少的次数使t不为S的子串。
用后缀自动机可以很快的处理这种有关子串问题。对S串建立后缀自动机,然后让t在自动机上跑,若t的当前字符与自动机的转移字符不一样时,修改串t的代价+1。在自动机上碰到转移字符只有‘1’或‘0’时,若t的当前字符与自动机唯一的转移方向一致,代价+1,否则不变,此时修改结束。然后最小的代价为答案。
在自动机上跑dfs,计算不出它的时间复杂度,没有任何剪枝(不会剪),妥妥的超时。然后抄袭了大佬的剪枝(dfs)终于过了。
代码:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> #include <queue> #include <map> using namespace std; typedef long long llt; const int INF = 0x3ffffff; const int N = 10010; struct state{ int len,link; map<char,int>next; }st[N*2]; string str; int sz,last; void sa_init(int n) { sz = last = 0; st[0].len = 0; st[0].link = -1; ++sz; for(int i = 0; i < 2*n; ++i) st[i].next.clear(); } void sa_extend(char c) { int cur = sz++; //新添加的状态结点 st[cur].len = st[last].len+1; int p; for(p = last; p != -1 && !st[p].next.count(c); p = st[p].link) st[p].next[c] = cur; if(p == -1) st[cur].link = 0; else{ int q = st[p].next[c]; if(st[p].len+1 == st[q].len) st[cur].link = q; else{ int clone = sz++; st[clone].len = st[p].len+1; st[clone].next = st[q].next; st[clone].link = st[q].link; for(; p != -1 && st[p].next[c] == q; p = st[p].link) st[p].next[c] = clone; st[q].link = st[cur].link = clone; } } last = cur; } int ans; //u当前自动机上匹配的结点,s子串上匹配的结点 void dfs(int u,int s,int e,int cnt) { if(u == sz-1 && s <= e || s > e || cnt >= ans) return; //剪枝,当前解小于已知最优解直接退出 char ch = str[s]; int t = st[u].next.count(ch); if(t == 0) ans = min(ans,cnt); else dfs(st[u].next[ch],s+1,e,cnt); ch = (str[s] == '1' ? '0' : '1'); t = st[u].next.count(ch); if(t == 0) ans = min(ans,cnt+1); else dfs(st[u].next[ch],s+1,e,cnt+1); } int main() { // freopen("d:\\k.in","r",stdin); // freopen("d:\\out.txt","w",stdout); int n,k; while(~scanf("%d%d",&n,&k) && n && k){ cin >> str; sa_init(str.length()); for(int i = 0; i < str.length(); ++i) sa_extend(str[i]); int a,b; for(int i = 0; i < k; ++i){ ans = INF; scanf("%d%d",&a,&b); if(a == b){ printf("Impossible\n"); continue; } dfs(0,a-1,b-1,0); if(ans >= INF) printf("Impossible\n"); else printf("%d\n",ans); } } return 0; }