20/08/01测试
T1
考场上的想法:
只有\(0\),\(1\)两种状态,可以二进制压缩。挺好的。
数据范围不大,可以搜索,但是肯定会炸。蒟蒻害怕。
而目标状态和起始状态都是给定的,可以用双端搜索优化。
感觉双端搜索是正解,然而之前打的很少,就只能自己yy了。
yy了好长时间终于yy出来了,但用的时间有点长,导致其他题的暴力分没拿到。
最可恨的是因为搜索时少判了情况丢了\(20\)分。其实考试时想到了但懒得改qaq。
考场代码
include <bits/stdc++.h>
using namespace std;
const int maxn = 20;
int n, m, vis[2][1<<12], dis[2][1<<12];
struct node{
int val[maxn];
}e[200];void bfs(){
queueq_start, q_end;
int qwq[11], qaq = 0;
for(int i = 1; i <= n; i ++) qwq[i] = 1;
for(int i = 1; i <= n; i ++) if(qwq[n-i+1]) qaq += 1<<(i-1);
q_start.push(qaq), q_end.push(0);
vis[0][qaq] = 1, vis[1][0] = 1;
while(q_start.size() or q_end.size()){
if(1 or 1 or 1 or 1){
int now = q_start.front();
q_start.pop();
int cnt = 0, cmp = now, a[11], tmp[11];
memset(tmp, 0, sizeof(tmp));
while(cmp){
tmp[++cnt] = cmp&1;
cmp >>= 1;
}
for(int i = 1; i <= n; i ++) a[i] = tmp[n-i+1];
int b[11];
for(int i = 1; i <= m; i ++){
for(int j = 1; j <= n; j ++){
if(e[i].val[j] ==-1) b[j] = 1;
if(e[i].val[j] == 1) b[j] = 0;
if(e[i].val[j] == 0) b[j] = a[j];
}
int turned = 0;
for(int i = 1; i <= n; i ++) if(b[n-i+1]) turned += 1<<(i-1);
if(!vis[0][turned]){
q_start.push(turned);
vis[0][turned] = 1;
dis[0][turned] = dis[0][now] + 1;
}
if(vis[1][turned]){
printf("%d\n", dis[0][turned]+dis[1][turned]);
return;
}
}
}
if(1 or 1 or 1 or 1){
int now = q_end.front();
q_end.pop();
int cnt = 0, cmp = now, a[11], tmp[11];
memset(tmp, 0, sizeof(tmp));
while(cmp){
tmp[++cnt] = cmp&1;
cmp >>= 1;
}
for(int i = 1; i <= n; i ++) a[i] = tmp[n-i+1];
int b[11];
for(int i = 1; i <= m; i ++){
for(int j = 1; j <= n; j ++){
if((e[i].val[j] ==-1 and !b[j])or(e[i].val[j] == 1 and b[j])) continue;
if(e[i].val[j] ==-1) b[j] = 0;
if(e[i].val[j] == 1) b[j] = 1;
if(e[i].val[j] == 0) b[j] = a[j];
}
int turned = 0;
for(int i = 1; i <= n; i ++) if(b[n-i+1]) turned += 1<<(i-1);
if(!vis[1][turned]){
q_end.push(turned);
vis[1][turned] = 1;
dis[1][turned] = dis[1][now] + 1;
}
if(vis[0][turned]){
printf("%d\n", dis[0][turned]+dis[1][turned]);
return;
}
}
}
}
printf("-1\n");
return;
}signed main(){
freopen("flame.in", "r", stdin);
freopen("flame.out", "w", stdout);
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i ++){
for(int j = 1; j <= n; j ++){
scanf("%d", &e[i].val[j]);
}
}
bfs();
return 0;
}
嘶,完了考试时把这道题想难了,数据太水,压根不用双端搜索,直接从一端bfs就行啊啊啊啊啊啊。
结果跑双端搜索还少判了情况丢了\(20\)分qaq。还花了好长时间导致其他题暴力分没拿!嘶,难受qaq。
想给出题人YY学长寄刀片过去。

思路:二进制压缩+搜索
超级简单,因为这道题丢了\(20+\)的分数心情不好不想写了qaq。
啊其实是我自己的问题,跟YY学长无关,发发牢骚而已,还是我自己没把控好时间的分配,怪我太菜了。蒟蒻反思orz。
代码
#include <bits/stdc++.h> using namespace std; const int maxn = 20; int n, m, vis[1<<12], dis[1<<12]; struct node{ int val[maxn]; }e[200]; void bfs(){ queue<int> q; int qwq[11], qaq = 0; for(int i = 1; i <= n; i ++) qwq[i] = 1; for(int i = 1; i <= n; i ++) if(qwq[n-i+1]) qaq += 1<<(i-1); q.push(qaq); vis[qaq] = 1; while(q.size()){ int now = q.front(); q.pop(); int cnt = 0, cmp = now, a[11], tmp[11]; memset(tmp, 0, sizeof(tmp)); while(cmp){ tmp[++cnt] = cmp&1; cmp >>= 1; } for(int i = 1; i <= n; i ++) a[i] = tmp[n-i+1]; int b[11]; for(int i = 1; i <= m; i ++){ for(int j = 1; j <= n; j ++){ if(e[i].val[j] ==-1) b[j] = 1; if(e[i].val[j] == 1) b[j] = 0; if(e[i].val[j] == 0) b[j] = a[j]; } int turned = 0; for(int i = 1; i <= n; i ++) if(b[n-i+1]) turned += 1<<(i-1); if(!vis[turned]){ q.push(turned); vis[turned] = 1; dis[turned] = dis[now] + 1; } } } printf("-1\n"); return; } signed main(){ scanf("%d%d", &n, &m); for(int i = 1; i <= m; i ++){ for(int j = 1; j <= n; j ++){ scanf("%d", &e[i].val[j]); } } bfs(); return 0; }
T2
贪心。考试时划水了没时间写了,最后二十分钟写了个残缺的搜索没调出来。
code
#include <bits/stdc++.h> using namespace std; long long read(){ long long s = 0, f = 1; char ch; while(!isdigit(ch = getchar())) (ch == '-') and (f = -f); for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48)); return s * f; } const int maxn = 1005; int n, m, high, wid, ans, cnt, tot, flag, vis[maxn], c[maxn]; struct people{ int h, w, der; }a[maxn]; int cmp(int a, int b){ return a > b; } signed main(){ freopen("photo.in", "r", stdin); freopen("photo.out", "w", stdout); n = read(); m = n/2; for(int i = 1;i <= n; i ++){ a[i].w = read(), a[i].h = read(); } ans = 1e9; for(int high = 1; high <= 1000; high ++){ cnt = 0, tot = 0, flag = 0, wid = 0; memset(c, 0, sizeof(c)); for(int i = 1; i <= n; i ++) { if(a[i].h > high and a[i].w > high){ flag = 1; break; } if(a[i].h > high and a[i].w <= high){ ++ cnt; wid += a[i].h; } if(a[i].h <= high and a[i].w > high){ wid += a[i].w; } if(a[i].h <= high and a[i].w <= high){ if(a[i].h < a[i].w){ c[++tot] = a[i].w - a[i].h; wid += a[i].w; } if(a[i].h >= a[i].w){ wid += a[i].w; } } } if(flag == 1 or cnt > m) continue; sort(c+1, c+tot+1, cmp); for(int i = 1; i <= m-cnt; i ++) wid -= c[i]; ans = min(ans, high*wid); } printf("%d", ans); fclose(stdin); fclose(stdout); return 0; }
T3
乱搞。但是别人普遍拿到了30分的暴力分,啊我没拿到orz。主要还是划水了qwq。
code
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6+10; int n, A, B, C, D, a[5010], b[5010], c[5010], d[5010], maxnn, cur, f[maxn], c1[maxn], c2[maxn], cnt1, cnt2; long long ans; signed main(){ freopen("eat.in", "r", stdin); freopen("eat.out", "w", stdout); scanf("%d%d%d%d%d", &n, &A, &B, &C, &D); for(int i = 1; i <= A; i ++) scanf("%d", &a[i]); for(int i = 1; i <= B; i ++) scanf("%d", &b[i]); for(int i = 1; i <= C; i ++) scanf("%d", &c[i]); for(int i = 1; i <= D; i ++) scanf("%d", &d[i]); for(int i = 1; i <= A; i ++){ for(int j = 1; j <= B; j++){ if(a[i] + b[j] <= n){ f[a[i] + b[j]]++; maxnn = max(maxnn, a[i] + b[j]); } } } for(int i = 0; i <= maxnn; i ++){ while(f[i]){ f[i]--; c1[++cnt1] = i; } } maxnn = 0; for(int i = 1; i <= C; i ++){ for(int j = 1; j <= D; j ++){ if(c[i] + d[j] <= n) { f[c[i] + d[j]]++; maxnn = max(maxnn, c[i] + d[j]); } } } for(int i = 0; i <= maxnn; i ++){ while(f[i]){ f[i]--; c2[++cnt2] = i; } } for(cur = cnt2; cur >= 1; cur--){ if(c1[1] + c2[cur] <= n){ break; } } for(int i = 1; i <= cnt1; i ++){ ans += cur; while(cur and c1[i + 1] + c2[cur] > n) cur--; } printf("%lld\n", ans); return 0; }

浙公网安备 33010602011771号