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(){
queue q_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
", 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
", dis[0][turned]+dis[1][turned]);
return;
}
}
}
}
printf("-1
");
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
");
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
", ans);
return 0;
}