第一天(前面咕了两天),210,没发挥好,凑合。
- 煎饼
一共切横 (h) 加竖 (v) 刀,则一共分成 ((h+1)*(v+1)) 块
显然 (@) 总和 (sum) 是 ((h+1)*(v+1)) 的倍数,不是就不可能达到
那么每块的大小就是 (dfrac{sum}{(h + 1) * (v+ 1)})
这样就可以可以明确每行每列的刀的位置
那么其他位置用二维前缀和check一下就行
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second
#define enter cout << endl
const int N = 110 ;
int n, m, r, c, cntr, cntc, xgm, cnt ;
int sum[N][N], a[N][N], row[N], col[N], psb[10 * N] ;
string s ;
int get(int X1, int Y1, int X2, int Y2) {
return sum[X2][Y2] - sum[X1 - 1][Y2] - sum[X2][Y1 - 1] + sum[X1 - 1][Y1 - 1] ;
}
void clear() {
cnt = 0, xgm = 0 ;
memset(sum, 0, sizeof(sum)) ;
}
signed main() {
int t ; scanf("%d", &t) ;
rep(rnd, 1, t) {
clear() ;
scanf("%d%d%d%d", &n, &m, &r, &c) ;
rep(i, 1, n) {
cin >> s ;
rep(j, 0, m - 1) a[i][j + 1] = (s[j] == '@') ? 1 : 0 ;
}
printf("Case #%d: ", rnd) ;
rep(i, 1, n)
rep(j, 1, m)
if (a[i][j] == 1) xgm++ ;
rep(i, 1, n)
rep(j, 1, m)
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j] ;
if (!xgm) {
puts("POSSIBLE") ;
continue ;
}
if (xgm % (r + 1) != 0 || xgm % (c + 1) != 0) {
puts("IMPOSSIBLE") ;
continue ;
}
int sz = xgm / ((r + 1) * (c + 1)) ;
int rowsz = xgm / (r + 1), colsz = xgm / (c + 1) ;
// cout << rowsz << " " << colsz << endl ;
cntr = cntc = 0 ;
int cur = 0 ;
rep(i, 1, n) if (get(row[cur] + 1, 1, i, m) == rowsz) row[++cntr] = i, cur++ ;
if (cur != r + 1) {
puts("IMPOSSIBLE") ;
continue ;
}
cur = 0 ;
rep(j, 1, m) if (get(1, col[cur] + 1, n, j) == colsz) col[++cntc] = j, cur++ ;
if (cur != c + 1) {
puts("IMPOSSIBLE") ;
continue ;
}
bool flg = true ;
rep(i, 1, cntr)
rep(j, 1, cntc)
if (get(row[i - 1] + 1, col[j - 1] + 1, row[i], col[j]) != sz) {
flg = false ;
break ;
}
if (flg) puts("POSSIBLE") ;
else puts("IMPOSSIBLE") ;
}
return 0 ;
}
- 机器人
这题很简单,裸的二分,普及组难度
二分答案,然后求出没个收银员的可手的甜甜圈数量,
看前 (R) 大的和是否 >= (B)
注意数量要与0取max
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second
#define int long long
const int N = 100010 ;
int n, k, m, cnt ;
int valid[N] ;
struct node {
int m, s, p ; // Max = m, tim = s * n + p
} a[N] ;
bool cmp1(node a, node b) {
return a.s < b.s ;
}
bool cmp2(node a, node b) {
return a.p < b.p ;
}
bool cmp3(node a, node b) {
return a.s * min(a.m, b.m) + a.p < b.s * min(a.m, b.m) + b.p ;
}
bool check(int tm) {
int rst = k, cnt = 0 ;
rep(i, 1, m) {
if (tm <= a[i].p) continue ;
valid[++cnt] = min(a[i].m, (tm - a[i].p) / a[i].s) ;
}
sort(valid + 1, valid + cnt + 1) ;
reverse(valid + 1, valid + cnt + 1) ;
rep(i, 1, min(n, cnt)) rst -= valid[i] ;
return rst <= 0 ;
}
void clear() {
}
signed main() {
freopen("robot.in", "r", stdin) ;
freopen("robot.out", "w", stdout) ;
int t ; scanf("%lld", &t) ;
rep(rnd, 1, t) {
clear() ;
scanf("%lld%lld%lld", &n, &k, &m) ; // robot, sum, sell
rep(i, 1, m) scanf("%lld%lld%lld", &a[i].m, &a[i].s, &a[i].p) ;
// sort(a + 1, a + m + 1, cmp1) ;
int l = 0, r = LONG_LONG_MAX / 2, mid ;
// cout<<LONG_LONG_MAX<<endl ;
while (l < r) {
int mid = (l + r) >> 1ll ;
if (check(mid)) r = mid ;
else l = mid + 1 ;
}
// rep(i, max(0ll, l - 5), r + 5)
// if (check(i)) {
// printf("%lld
", i) ;
// break ;
// }
printf("Case #%d: %lld
", rnd, l) ;
}
return 0 ;
}
- 面包师
这个题有点小难,考试时瞎搞骗分40
其实就是个背包,只不过稍有变化
每个面包要么不切,要么切开,
切开对答案的贡献就是 ([2*min(x,y),2*sqrt{(x^2+y^2)}])
所以问题就是取一些面包,然后使他们的贡献(区间)尽可能接近p
设每一个面包的贡献是 ([low,up]), 令 (p-sum_{i=1}^n 2*(x+y)=k)
首先可以观察到必定满足 (Σlow[i]<=p)
会观察到 (Σlow[i]) 范围不叫小,大概是 (10^4) 到 (10^5) 这么大
那么可以考虑背包
dp[i]表示 (Σlow=i) 时 (Σup) 的最大值
然后在(dp[0,min(Σlow,p)]) 的范围上找一个最大的,如果大于 (p) 就是 (p)
如果没有就是它自己
输出就行了
还算基础(这你都做不对!)
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second
const int N = 100010 ;
int n, p, tot, Low ;
int w[N], h[N], t[N] ;
double delt[N], f[N] ;
signed main() {
int T ;
scanf("%d", &T) ;
rep(rnd, 1, T) {
scanf("%d%d", &n, &p) ;
memset(t, 0, sizeof(t)) ;
Low = tot = 0 ;
rep(i, 1, n) {
scanf("%d%d", &w[i], &h[i]) ;
if (h[i] > w[i]) swap(w[i], h[i]) ;
tot += h[i] ; Low += h[i] + w[i] ;
delt[i] = sqrt(1.0 * w[i] * w[i] + 1.0 * h[i] * h[i]) - h[i] ;
}
rep(i, 0, tot) f[i] = 0 ;
t[0] = 1 ;
rep(i, 1, n)
per(j, tot, h[i])
if (t[j - h[i]])
f[j] = max(f[j], f[j - h[i]] + delt[i]), t[j] = 1 ;
double ans = 0 ;
rep(i, 0, tot) if (t[i] && Low * 2 + i * 2 <= p) ans = max(ans, min((double) p, f[i] * 2 + Low * 2 + i * 2)) ;
printf("Case #%d: %.6lf
", rnd, ans) ;
}
return 0 ;
}