5.7 ~ 5.12 刷题列表
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> using namespace std; int n, m, t; int ans; int a[25]; int rest[25]; int pos; void dfs(int now, int sum) { if (now == n + 1){ ans = max(ans, sum); return ; } if (sum + n + 1 - now <= ans) return ;//剪枝 if (rest[pos] >= a[now]){ //xuan ze zhe ge rest[pos] -= a[now]; dfs(now + 1, sum + 1); rest[pos] += a[now]; } if (pos < m and rest[pos+1] >= a[now]) { // xuan ze xia yi ge pos++; rest[pos] -= a[now]; dfs(now + 1, sum + 1); rest[pos] += a[now]; pos--; } dfs(now + 1, sum); //bu xuan ze } int main() { cin >> n >> t >> m; for (register int i = 1 ; i <= n ; i ++) scanf("%d", &a[i]); for (register int i = 1 ; i <= m ; i ++) rest[i] = t; dfs(1, 0); cout << ans << endl; return 0; }
Noip2011 聪明的质检员 二分答案,前缀和
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define int long long int n, m, s; int w[200010], v[200010]; int sw[200010], sv[200010]; int li[200010], ri[200010]; int l, r, mid; int res, sum; int ans = 0x7f7f7f7f7f7f7f7f7f; bool check(int x) { res = 0, sum = 0; int aa = 0; for (int i = 1 ; i <= n ; i ++){ if(w[i] < x) sv[i] = sv[i-1], sw[i] = sw[i-1]; else { sv[i] = sv[i-1] + v[i]; sw[i] = sw[i-1] + 1; } } for (int i = 1 ; i <= m ; i ++){ res += (sw[ri[i]] - sw[li[i]-1]) * (sv[ri[i]] - sv[li[i]-1]); } // printf("mid = %d, res = %d\n", x, res); sum = abs(res - s); if(res > s) return 1; return 0; } signed main() { cin >> n >> m >> s; for (int i = 1 ; i <= n ; i ++){ scanf("%lld%lld", &w[i], &v[i]); sv[i] = sv[i-1] + v[i]; r = max(r, w[i]); } for (int i = 1 ; i <= m ; i ++){ scanf("%lld%lld", &li[i], &ri[i]); } while(l <= r){ mid = l + r >> 1; bool f = check(mid); ans = min(ans, sum); if(f){ l = mid + 1; } else r = mid - 1; } cout << ans << endl; return 0; }
HAOI2010音量调节 DP水题(我不会说我因数组开小WA了n次)
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> using namespace std; int n, m, s; int a[52]; bool dp[52][1010];//第i次, 音量为j是否可行 int main() { cin >> n >> m >> s; for (register int i = 1 ; i <= n ; i ++){ scanf("%d", &a[i]); } dp[0][m] = 1; for (register int i = 1 ; i <= n ; i ++){ for (register int j = 0 ; j <= s ; j ++){ if (dp[i-1][j]){ if (j + a[i] <= s) dp[i][j+a[i]] = 1; if (j - a[i] >= 0) dp[i][j-a[i]] = 1; } } } for (register int i = s ; i >= 0 ; i --){ if(dp[n][i]) { cout << i << endl; return 0; } } puts("-1"); return 0; }
USACO 蹄子剪刀布 DP水题
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define regi register int n, m; int a[100010]; int dp[100010][51][4]; inline int win(int x, int y) { if (x == 1 and y == 2) return 1; if (x == 2 and y == 3) return 1; if (x == 3 and y == 1) return 1; return 0; } inline int Large(int x, int y, int z) { if (x > y) return x > z ? x : z; else return y > z ? y : z; } int ans1, ans2, ans3; int main() { cin >> n >> m; for (regi int i = 1 ; i <= n ; i++){ char c; cin >> c; if (c == 'P') a[i] = 1; else if (c == 'H') a[i] = 2; else a[i] = 3; } for (regi int i = 1 ; i <= n ; i ++){ dp[i][0][1] = dp[i-1][0][1] + win(1, a[i]); dp[i][0][2] = dp[i-1][0][2] + win(2, a[i]); dp[i][0][3] = dp[i-1][0][3] + win(3, a[i]); } for (regi int i = 1 ; i <= n ; i ++){ for (regi int j = 1 ; j <= m ; j ++){ dp[i][j][1] = Large(dp[i-1][j][1], dp[i-1][j-1][2], dp[i-1][j-1][3]) + win(1, a[i]); dp[i][j][2] = Large(dp[i-1][j][2], dp[i-1][j-1][1], dp[i-1][j-1][3]) + win(2, a[i]); dp[i][j][3] = Large(dp[i-1][j][3], dp[i-1][j-1][1], dp[i-1][j-1][2]) + win(3, a[i]); } } cout << Large(dp[n][m][1], dp[n][m][2], dp[n][m][3]) << endl;; return 0; }
USACO 环绕岛屿 直接暴力 挺好的题,我写了题解 ,戳这里
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> #include <cstring> using namespace std; #define regi register int n; int fa[505]; inline int Find(int x) { return x == fa[x] ? x : fa[x] = Find(fa[x]); } int dis[505][505]; int cnt; int ans = 0x7f7f7f7f; int pos[505]; int main() { cin >> n; for (regi int i = 1 ; i <= n ; i ++) fa[i] = i; memset(dis, 0x7f, sizeof dis); for (regi int i = 1 ; i <= n ; i ++){ int x, y; scanf("%d%d", &x, &y); int fx = Find(x), fy = Find(y); if (fx != fy) fa[fx] = fy; } for (regi int i = 1 ; i <= n ; i ++){ if (fa[i] == i) pos[++cnt] = i; } for (regi int i = 1 ; i <= n ; i ++){ int fi = Find(i); for (regi int j = 1 ; j <= n ; j ++){ int fj = Find(j); int d; scanf("%d", &d); dis[fi][fj] = min(dis[fi][fj], d); } } for (regi int i = 1 ; i <= cnt ; i ++){ int sum = 0; for (regi int j = 1 ; j <= cnt ; j ++){ if (i == j) continue; sum += dis[pos[i]][pos[j]]; } ans = min(ans, sum); } // printf("dis==%d\n", dis[4][10]); cout << ans * 2 << endl; return 0; }
USACO吃巧克力 二分水题, 坑点 : 没吃完的放到最后一天吃,还有记得开long long, 坑了我5次
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> #include <cstring> using namespace std; #define regi register #define int long long int n, d; int a[50005]; int tim[50005]; int b[50005]; int l = 1, r, mid; int ans; bool check(int x) { int now = 0, j = 1; for (regi int i = 1 ; i <= d ; i ++){ now /= 2; while (now < x and j <= n){ now += a[j]; b[j] = i; j ++; } if (now < x) return 1; } for (regi int i = 1 ; i <= n ; i ++) tim[i] = d; for (regi int i = 1 ; i < j ; i ++) tim[i] = b[i]; return 0; } signed main() { cin >> n >> d; for (regi int i = 1 ; i <= n ; i ++){ scanf("%lld", &a[i]); r += a[i]; } while (l <= r){ mid = l + r >> 1; bool f = check(mid); if (f){ r = mid - 1; } else{ l = mid + 1; ans = mid; } } cout << ans << endl; for (regi int i = 1 ; i <= n ; i ++){ printf("%lld\n", tim[i]); } return 0; }