2023/6/5---刷题

Problem - C1 - Codeforces (Unofficial mirror by Menci)

一个好区间中的所有子区间都是好的,使用双指针求出每段最大好区间。

const int MAX = 2e5 + 5;
int a[MAX];
void solve() {
	int n;
	int l = 1;
	long long ans = 0;
	cin >> n;
	for (int i = 1; i <= n; ++i) cin >> a[i];
	for (int i = 1; i <= n; ++i) {  //i为右指针,l为左指针
		while (a[i] < i - l + 1) ++l;   //得到以i为终点的最大好区间
		ans += (i - l + 1);
	}
	cout << ans << '\n';
}

Problem - B - Codeforces (Unofficial mirror by Menci)

要求重新构造的b数组满足a[i]=gcd(b[i],b[i+1]),易构造b[i]=lcm(a[i-1],a[i]),边界b[0]=a[0],b[n]=a[n-1],后遍历判断构造出的b数组是否满足条件。

int gcd(int a, int b) {
	return !b ? a : gcd(b, a % b);
}
void solve() {
	int n;
	cin >> n;
	int* a = new int[n + 1];
	int* b = new int[n + 1];
	for (int i = 0; i < n; i++)cin >> a[i];
	b[0] = a[0], b[n] = a[n - 1];        //边界
	for (int i = 1; i < n; i++) {
		b[i] = a[i] / gcd(a[i], a[i - 1]) * a[i - 1];  //最小公倍数构造b
	}
	for (int i = 0; i < n; i++) {    //判断b数组是否满足条件
		if (a[i] != gcd(b[i], b[i + 1])) {
			cout << "NO\n";
			return;
		}
	}
	cout << "YES\n";
}

Fliptile - POJ 3279 - Virtual Judge

#define inf 0x3fffffff
int n, m;
int ma[20][20];    //输入数据
int maap[20][20];   //最优解 
int teep[20][20];  //每一个位置的翻转次数
int dx[4] = { 0,0,-1,1 };  //四个方向
int dy[4] = { 1,-1,0,0 };

bool getcol(int x,int y) {   //判断(x,y)的颜色,累加(x,y)本身颜色和四周的翻转次数
    int temp = teep[x][y] + ma[x][y];
    for (int i = 0; i < 4; i++) {
        int x1 = x + dx[i];
        int y1 = y + dy[i];
        if (x1<1 || y1<1 || x1>n || y1>m)continue;
        temp += teep[x1][y1];
    }
    return temp & 1;   //相当于temp%2,若最终结果为奇,说明(x,y)最终颜色为1,下一行需要翻转
                          //否则不用
}

int dfs() {
    for (int i = 2; i <= n; i++) {     //从第2行开始
        for (int j = 1; j <= m; j++) {
            if (getcol(i - 1, j))  //求上一行的颜色,判断该行是否需要翻转
                teep[i][j] = 1;
        }
    }
    int temp = 0;
    for (int i = 1; i <= m; i++) {   //判断最后一行是否有黑色,如果有则完成不了
        if (getcol(n, i))return inf;
    }
    for (int i = 1; i <= n; i++) {   //累计总翻转次数
        for (int j = 1; j <= m; j++) {
            temp += teep[i][j];
        }
    }
    return temp;
}

int main() {
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)cin >> ma[i][j];
    int ans = inf;
    for (int i = 0; i < (1 << m); i++) {  //枚举第一行的所有翻转情况(采取二进制的枚举方式)
        memset(teep, 0, sizeof(teep));
        for (int j = 1; j <= m; j++)    //给第一行赋值
            teep[1][m - j + 1] = (i >> (j - 1)) & 1;
        int cnt = dfs();
        if (cnt < ans) { //保存最优解
            ans = cnt;
            memcpy(maap, teep, sizeof(teep));
        }
    }
    if (ans == inf)cout << "IMPOSSIBLE\n";
    else
        for (int i = 1; i <= n; i++, cout << '\n')
            for (int j = 1; j <= m; j++)cout << maap[i][j] << ' ';

    return 0;
}

Pots - POJ 3414 - Virtual Judge

把A,B当前水量和当前操作数作为队列节点,进行bfs,求得最小操作数。

E - Pots ---bfs
int a, b, c;  //A,B,C
typedef struct {
	int x, y, t;  //A,B当前水量,当前操作数
	int setp[1005];  //每一步的操作类型
}node;  //队列节点
char pt[7][20]={"","FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};
//6种操作
int vis[105][105];  //标记是否访问

int bfs() {
	queue<node>q;
	q.push(node{ 0,0,0 });
	vis[0][0] = 1;
	while (!q.empty()) {
		node t = q.front();
		q.pop();
		if ((t.x == c) || (t.y == c)) {  //终点
			cout << t.t << '\n';
			for (int i = 1; i <= t.t; i++) {
				cout << pt[t.setp[i]] << '\n';
			}
			return 1;
		}
		for (int i = 1; i <= 6; i++) {
			node t1 = t;
			int k = t.x + t.y;  
			if (i == 1) {  //A填满
				t1.x = a;
			}
			else if (i == 2) { //B填满
				t1.y = b;
			}
			else if (i == 3) { //A清空
				t1.x = 0;
			}
			else if (i == 4) { //B清空
				t1.y = 0;
			}
			else if (i == 5) { //A倒给B
				if (k >= b) {
					t1.y = b;
					t1.x = k - b;
				}
				else { 
					t1.y = k;
					t1.x = 0;
				}
			}
			else {    //B倒给A
				if (k >= a) {
					t1.x = a;
					t1.y = k - a;
				}
				else {
					t1.x = k;
					t1.y = 0;
				}
			}
			if (!vis[t1.x][t1.y]) {
				vis[t1.x][t1.y] = 1;
				t1.setp[++t1.t] = i;  //记录每一步的操作类型
				q.push(t1);     //操作后的状态入队
			}
		}
	}
	return 0;  //若始终没有水箱有C升水,返回0
}


int main() {
	ios::sync_with_stdio(false);
	cin >> a >> b >> c;
	if (bfs() == 0)cout << "impossible\n";
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

akb000

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值