SGU 167.I-country

时间限制:0.75s

空间限制:6M

题意:

在一个n*m(n,m<=15)的网格中,每个格子有一个值,现在从网格中取出k(k<=n*m)个,保证在选中的格子中从任意一个格子去另外的所有格子最多只用到四种(上,下,左,右)操作中的两种,并使得到的值最大。输出该值和选中的格子坐标。



Solution

    从选中的网格的任意一个去所有格子只用两种操作:

左图一种满足条件的网格集合,右图的(1,3)到(3,2)必需使用(左,下,右)三种操作才能到达,是不符合要求的。

注意到,满足条件的网格集合一定不会出现凹形,因为凹形的上下两个突出点中的格子不可能只用两个操作到达。

由此用0,1记录左右两边是 向外突出还是向内收缩。

当一行的一边向内收缩时便不可以再向外突出了。

接下来是按行dp

f[row][l][r][opl][opr][k],代表第row行,取第l列带第r列的格子,左边格子突出状态为opl,右边为opr,当前共选择了k个格子

记录路径时如果用结构体记录下所有的状态的上一个状态需要15*15*2*2*225 * size(int)*6的空间.

爆一次内存后,想到对于上一个状态row和k可以推出,只需要记录(l,r,opl,opr)即可,而(l,r,opl,opr)都是不超过16的数,那么可以用一个int形用16进制存下

存的时候用 record=(l << 12) + (r << 8) + (opl << 4) + (opr)

用的时候

上一个(row,l,r,opl,opr,k)

可以由当前的(row - 1, (record >> 12) % 16, (record >> 8) % 16, (record >> 4) % 16, record % 16, k - r + l - 1)得到

这道题需要注意的地方有很多,不一一列举.总的来说是一道值得一做的好题

参考代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#define pdx pr[row][l][r][opl][opr][k]
#define val(r,a,b) g[r][b] - g[r][a - 1]
using namespace std;
int f[16][16][16][2][2][230], g[16][16];
int pr[16][16][16][2][2][230];
int n, m, k, ans;
int a, al, ar, aol, aor;
/*
       op=0    /  左突
       op=1    \  右突
*/
//当前状态向下更新
void update (int row, int l, int r, int opl, int opr, int s) {
	if (row == n) return ;
	for (int nl = (opl == 0 ? 1 : l); nl <= r; nl++)
		for (int nr = max (l, nl); nr <= (opr == 0 ? r : m); nr++) {
			int t1, t2;
			if (nl == l) t1 = opl;
			else
				t1 = (nl < l ? 0 : 1);
			if (nr == r) t2 = opr;
			else
				t2 = (nr < r ? 0 : 1);
			if (f[row + 1][nl][nr][t1][t2][s + (nr - nl + 1)] <
                              f[row][l][r][opl][opr][s] + val (row + 1, nl, nr) ) {
				f[row + 1][nl][nr][t1][t2][s + (nr - nl + 1)] =
                              f[row][l][r][opl][opr][s] + val (row + 1, nl, nr);
				//记录上一个状态   ,  16进制状态压缩
				pr[row + 1][nl][nr][t1][t2][s + (nr - nl + 1)] =
				              (l << 12) + (r << 8) + (opl << 4) + (opr);
			}
		}
}

void dp() {
	for (int row = 1; row <= n; row++)
		for (int l = 1; l <= m; l++)
			for (int r = l; r <= m; r++)
				for (int opl = 0; opl < 2; opl++)
					for (int opr = 0; opr < 2; opr++) {
						f[row][l][r][opl][opr][r - l + 1] = g[row][r] - g[row][l - 1];
						for (int s = r - l + 1; s <= k; s++)
							if (f[row][l][r][opl][opr][s] > 0 ) {
								update (row, l, r, opl, opr, s);
								if (s == k)//记录最大解
									if (f[row][l][r][opl][opr][s] > ans) {
										ans = f[row][l][r][opl][opr][s];
										a = row, al = l, ar = r, aol = opl, aor = opr;
									}
							}
					}
}
//输出
void write (int row, int l, int r, int opl, int opr, int k) {
	if (row == 0 || k <= 0) return;
	for (int i = l; i <= r; i++)
		printf ("%d %d\n", row, i);
	write (row - 1, (pdx >> 12) % 16, (pdx >> 8) % 16,
                      (pdx >> 4) % 16, pdx % 16, k - r + l - 1);
}
int main() {
#ifndef ONLINE_JUDGE
	freopen ("in.txt", "r", stdin);
#endif // oline_judge
	scanf ("%d %d %d", &n, &m, &k);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) {
			scanf ("%d", &g[i][j]);
			g[i][j] += g[i][j - 1];
		}
	memset (f, -1, sizeof f);
	dp();
	printf ("Oil : %d\n", ans);
	write (a, al, ar, aol, aor, k);
	return 0;
}

  

  

SGU 167.I-country,布布扣,bubuko.com

时间: 2024-10-12 19:37:38

SGU 167.I-country的相关文章

sgu 463 - Walking around Berhattan

K - Walking around Berhattan Time Limit:250MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice SGU 463 Description As you probably know, Berhattan is a district of Berland's largest city and it consists of equal squar

SGU 407 Number of Paths in the Empire dp+java大数

SGU 407 407. Number of Paths in the Empire Time limit per test: 0.75 second(s) Memory limit: 65536 kilobytes input: standard output: standard During the period of Tsam dynasty ruling people rarely fought against each other and their neighbours, becau

Photoshop技能167个经典的Photoshop技巧大全

Photoshop技能167个经典的Photoshop技巧大全 学PS基础:Photoshop 技能167个­ 经典的Photoshop技巧大全,如果你是初级阶段的水平,熟读此文并掌握,马上进阶为中级水平.绝对不是广告噢. ­ 1. 快速打开文件­ 双击Photoshop的背景空白处(默认为灰色显示区域)即可打开选择文件的浏览窗口.­ 2. 随意更换画布颜色­ 选择油漆桶工具并按住Shift点击画布边缘,即可设置画布底色为当前选择的前景色.如果要还原到默认的颜色,设置前景色为25%灰度 (R19

HDU5723 Abandoned country 最小生成树+深搜回溯法

Description An abandoned country has n(n≤100000) villages which are numbered from 1 to n. Since abandoned for a long time, the roads need to be re-built. There are m(m≤1000000) roads to be re-built, the length of each road is wi(wi≤1000000). Guarante

【SGU 390】Tickets (数位DP)

Tickets Description Conductor is quite a boring profession, as all you have to do is just to sell tickets to the passengers. So no wonder that once upon a time in a faraway galaxy one conductor decided to diversify this occupation. Now this conductor

ACM: SGU 101 Domino- 欧拉回路-并查集

sgu 101 - Domino Time Limit:250MS     Memory Limit:4096KB     64bit IO Format:%I64d & %I64u Description Dominoes – game played with small, rectangular blocks of wood or other material, each identified by a number of dots, or pips, on its face. The bl

hdu 5723 Abandoned country 最小生成树+子节点统计

Abandoned country Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3006    Accepted Submission(s): 346 Problem Description An abandoned country has n(n≤100000) villages which are numbered from 1

HDU计算机学院大学生程序设计竞赛(2015’12)The Country List

The Country List Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2598    Accepted Submission(s): 615 Problem Description As the 2010 World Expo hosted by Shanghai is coming, CC is very honorable

【单调队列】【cogs825】【RQNOJ 167】免费午餐

825. [RQNOJ 167] 免费午餐 ★☆ 输入文件:lunch.in 输出文件:lunch.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] 为了增加顾客,Sally的店铺决定提供免费午餐,顿时门庭若市,但是不久Sally的原材料不足了-.因此Sally决定公布一项决定:凡是来本店吃免费午餐的,一天吃能吃一次,吃的数量必须比上一次吃的少,且免费午餐将只有N个种类任君选择,为了能吃到最多的免费午餐,你将如何安排每日吃的数量呢? [输入文件] 第一行一个数N,表示免费