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(){
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;
}

原文地址:https://www.cnblogs.com/Vanyun/p/13413789.html