第一题:SPFA,最难的还是读入,一般读入接上一行的 ;
#include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> using namespace std; const int M = 4005; int S, T, p, h[M], tot, dis[M]; bool inq[M]; struct edge{int v, nxt;}G[M]; void add(int u, int v){ G[++tot].v = v; G[tot].nxt = h[u]; h[u] = tot; } inline int rec(int z){ int t = (z + 19) / 20 + z; while(t - (t + 19) / 20 < z)t++; return t; } void spfa(){ queue <int> Q; memset(dis, 127, sizeof(dis)); memset(inq, 0, sizeof(inq)); Q.push(T); dis[T] = p; inq[T] = 1; while(!Q.empty()){ int u = Q.front(); Q.pop(); inq[u] = 0; for(int i = h[u]; i; i = G[i].nxt){ int v = G[i].v; int w = u >= 100 ? rec(dis[u]) : dis[u] + 1; if(w < dis[v]){ dis[v] = w; if(!inq[v])Q.push(v), inq[v] = 0; } } } } inline void get(char a, char b){ int u, v; if(a <='Z' && a >='A') u = a-'A' + 100; else u = a-'a'; if(b <='Z' && b >='A') v = b-'A' + 100; else v = b-'a'; add(v, u); add(u, v); } void init(char a, char b){ int u, v; if(a <='Z' && a >='A') u = a-'A' + 100; else u = a-'a'; if(b <='Z' && b >='A') v = b-'A' + 100; else v = b-'a'; S = u, T = v; } void cls(){ memset(h, 0, sizeof(h)); tot = 0; } int main(){ freopen("toll.in","r",stdin); freopen("toll.out","w",stdout); int n, idc = 0; while(scanf("%d", &n) == 1 && n != -1){ idc++; cls(); char a, b, s, t; for(int i = 1; i <= n; i++){ scanf(" %c %c", &a, &b); // printf("%c %c ", a, b); get(a, b); } scanf("%d %c %c", &p, &s, &t); //printf("start %c %c ",s, t); init(s, t); spfa(); printf("Case %d: %d ", idc,dis[S]); } }
第二题:LIS即为答案,一个逆序对一条边,只有LIS里面没有边,应该多想一下,这道题很简单,但我方向完全偏了;
第三题:搜索+剪枝,所有数据都很小,所以可以实际跑的很快,本来想状压没搞出来;
#include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> using namespace std; #define For(a, b, c) for(int a = b; a <= c; a++) const int M = (1 << 14) + 1; int visr[M], visg[M], visw[M], ans, n; struct POINT{int sr,sg,kr,kg,kw;}d[15]; inline bool better(int s, int rr, int gg, int ww){ int nw = visw[s], tt = visr[s] - rr; if(tt > 0) ww -= tt; else nw += tt; if(ww + gg < visg[s] + nw || ( rr == visr[s] && gg == visg[s] && ww == visw[s]) )return 0; visr[s] = max(visr[s], rr); visw[s] = max(visw[s], ww); visg[s] = max(visg[s], gg); return 1; } void dfs(int dep, int sta, int rr, int gg, int ww){ //printf("%d %d %d %d ",sta, rr,gg,ww); ans = max(ans, rr + gg + ww); if(dep == n + 1)return ; if(!better(sta, rr, gg, ww))return; for(int i = 1; i <= n; i++) if(!(sta & (1 << (i - 1)))){ if(d[i].sr <= rr + ww){ int nr = rr >= d[i].sr ? rr - d[i].sr : 0; int nw = rr >= d[i].sr ? ww : ww - (d[i].sr - rr); int ng = gg >= d[i].sg ? gg - d[i].sg : 0; nw = gg >= d[i].sg ? nw : nw - (d[i].sg - gg); if(nw < 0)continue; dfs(dep + 1, sta | (1 << (i - 1)), nr + d[i].kr, ng + d[i].kg, nw + d[i].kw); } } } int main(){ //freopen("room.in","r",stdin); //freopen("room.out","w",stdout); int k0, k1, k2; scanf("%d", &n); memset(visg, -1, sizeof(visg)); memset(visr, -1, sizeof(visr)); memset(visw, -1, sizeof(visw)); For(i, 1, n) scanf("%d", &d[i].sr); For(i, 1, n) scanf("%d", &d[i].sg); For(i, 1, n) scanf("%d", &d[i].kr); For(i, 1, n) scanf("%d", &d[i].kg); For(i, 1, n) scanf("%d", &d[i].kw); /* For(i, 1, n) d[i].tot = d[i].kr + d[i].kg + d[i].kw; */ scanf("%d%d%d", &k0, &k1, &k2); //0 red 1 green 2 white ans = k0 + k1 + k2; dfs(1, 0, k0, k1, k2); printf("%d ",ans); }
今天题应该是很水的,然而考的不好,思维僵硬了;