MDeath-Kid

- M I T & Y
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

USACO 1.4

Posted on 2011-11-21 09:23  MDeath-Kid  阅读(441)  评论(0编辑  收藏  举报

PROB Packing Rectangles [ANALYSIS]----第一题是3天前看到的,事隔一课考试,全校答辩,今天终于A出来了,每天都在想,都在想,终于对这个题目比较明白了。

/*
	solution 1
	1	枚举排列数
	2	枚举翻转
	3	按6种情况枚举最小的
	4	所有情况记录所有最小值
*/

int rectx[4],recty[4];
int meijux[4],meijuy[4];
bool vis[4];

int sumx,sumy,sumarea = INT_MAX;
map<PII,int> vec;
map<PII,int>::iterator p;

void update(int x,int y)
{
	if(sumarea > x * y) {
		sumarea = x * y;
		vec.clear();
		vec[make_pair(min(x,y),max(x,y))] = 1;
	} else if(sumarea == x * y) {
		vec[make_pair(min(x,y),max(x,y))] = 1;
	}
}

int maxb(int a=0,int b=0,int c=0,int d=0)
{
	return max(a,max(b,max(c,d)));
}

//	判断函数
void check()
{
	//	case 1
	//	0 1 2 3
	sumx = meijux[0] + meijux[1] + meijux[2] + meijux[3];
	sumy = maxb(meijuy[0],meijuy[1],meijuy[2],meijuy[3]);

	update(sumx, sumy);

	//	case 2
	//	0 1 2
	//	  3
	sumx = maxb(meijux[0] + meijux[1] + meijux[2],meijux[3]);
	sumy = meijuy[3] + maxb(meijuy[1],meijuy[2],meijuy[0]);

	update(sumx,sumy);

	//	case 3
	//	0 1 2
	//	  3 2
	sumx = meijux[2] + maxb(meijux[0] + meijux[1],meijux[3]);
	sumy = maxb(meijuy[3] + maxb(meijuy[0],meijuy[1]),meijuy[2]);

	update(sumx,sumy);
	//	case 4
	//	0 1 3
	//	  2
	sumx = maxb(meijux[1],meijux[2]) + meijux[0] + meijux[3];
	sumy = maxb(meijuy[1] + meijuy[2],meijuy[0],meijuy[3]);

	update(sumx,sumy);
	//	case 5

	//	case 6
	//	0 1
	//	2 3
	sumy = maxb(meijuy[0] + meijuy[2],meijuy[1] + meijuy[3]);
	if(meijuy[2] >= meijuy[3]) {
		if(meijuy[2] >= meijuy[3] + meijuy[1]) {
			sumx = maxb(maxb(meijux[1],meijux[3]) + meijux[2],meijux[0]);
		} else {
			sumx = maxb(meijux[2] + meijux[1],meijux[2] + meijux[3],meijux[0] + meijux[1]);
		}
	} else {
		if(meijuy[3] >= meijuy[0] + meijuy[2]) {
			sumx = maxb(maxb(meijux[0],meijux[2]) + meijux[3],meijux[1]);
		} else {
			sumx = maxb(meijux[2] + meijux[3],meijux[0] + meijux[3] ,meijux[0] + meijux[1]);
		}
	}
	//DB(sumx<<" "<<sumy);
	update(sumx,sumy);
}


void dfs(int depth)
{
	if(depth == 4) {

		check();
		return;
	}

	//	全排列枚举
	F(i,4){
		if(!vis[i]) {
			//DB(i);
			vis[i] = 1;
			//	横竖枚举
			F(j,2) {
				if(j == 0) {
					meijux[depth] = rectx[i];
					meijuy[depth] = recty[i];
				} else {
					meijux[depth] = recty[i];
					meijuy[depth] = rectx[i];
				}
				dfs(depth + 1);
			}
			vis[i] = 0;
		}
	}
	return;
}

int main()
{
	FOPENTI
	FOPENTO
	F(i,4) SCFD(rectx[i],recty[i]);
	SET(vis,0);
	dfs(0);
	PCFLN(sumarea);
	for(p = vec.begin();p != vec.end();p++){
		printf("%d %d\n",p->first.first,p->first.second);
	}
}

我这里用map判断重复的,然后对应题目的6个情况,事实证明不考虑第5种情况也行,和第四种重复,第6种要分开情况考虑,每个人分类不同,但是肯定是安装 2 号与 3 号木块的高度进行分类的(其实第6中和前面还是有重复的)case 1 ~ 5在题目上面很清楚,就不说了只说case 6.

image

高度很容易计算:

sumy = maxb(meijuy[0] + meijuy[2],meijuy[1] + meijuy[3]);
//	sumx 安装下面进行分类,只是sumx 取那两个木块的最大值有所变化
if(meijuy[2] >= meijuy[3]) {
		if(meijuy[2] >= meijuy[3] + meijuy[1]) {
			sumx = maxb(maxb(meijux[1],meijux[3]) + meijux[2],meijux[0]);
		} else {
			sumx = maxb(meijux[2] + meijux[1],meijux[2] + meijux[3],meijux[0] + meijux[1]);
		}
	} else {
		if(meijuy[3] >= meijuy[0] + meijuy[2]) {
			sumx = maxb(maxb(meijux[0],meijux[2]) + meijux[3],meijux[1]);
		} else {
			sumx = maxb(meijux[2] + meijux[3],meijux[0] + meijux[3] ,meijux[0] + meijux[1]);
		}
	}
这次把AC的case贴出来。以后用。。题目debug了两次,第一次是手贱,‘,’ 打错 ‘+’,结果maxb是带默认参数的,没报错,WA。。第二次是情况6考虑错了,重新考虑,A了!外星人
USER: Rain M [m3324631]
TASK: packrec
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 3188 KB]
   Test 2: TEST OK [0.000 secs, 3188 KB]
   Test 3: TEST OK [0.000 secs, 3188 KB]
   Test 4: TEST OK [0.000 secs, 3188 KB]
   Test 5: TEST OK [0.000 secs, 3188 KB]
   Test 6: TEST OK [0.000 secs, 3188 KB]
   Test 7: TEST OK [0.000 secs, 3188 KB]
   Test 8: TEST OK [0.000 secs, 3188 KB]
   Test 9: TEST OK [0.000 secs, 3188 KB]
   Test 10: TEST OK [0.000 secs, 3188 KB]
   Test 11: TEST OK [0.000 secs, 3188 KB]
   Test 12: TEST OK [0.000 secs, 3188 KB]
   Test 13: TEST OK [0.000 secs, 3188 KB]
   Test 14: TEST OK [0.000 secs, 3188 KB]
   Test 15: TEST OK [0.000 secs, 3188 KB]
   Test 16: TEST OK [0.000 secs, 3188 KB]
   Test 17: TEST OK [0.000 secs, 3188 KB]
   Test 18: TEST OK [0.000 secs, 3188 KB]
   Test 19: TEST OK [0.000 secs, 3188 KB]
   Test 20: TEST OK [0.000 secs, 3188 KB]
   Test 21: TEST OK [0.000 secs, 3188 KB]

All tests OK.
Your program ('packrec') produced all correct answers!  This is your
submission #4 for this problem.  Congratulations!

Here are the test data inputs:

------- test 1 ----
1 2
2 3
3 4
4 5
------- test 2 ----
20 20
20 20
20 20
20 20
------- test 3 ----
4 5
5 4
4 5
16 1
------- test 4 ----
4 5
2 5
5 2
2 10
------- test 5 ----
12 18
4 6
2 17
19 3
------- test 6 ----
10 10
5 5
15 15
20 20
------- test 7 ----
1 1
1 20
1 20
20 20
------- test 8 ----
5 8
3 12
15 4
14 10
------- test 9 ----
4 5
5 6
6 4
4 5
------- test 10 ----
1 5
5 10
10 15
15 20
------- test 11 ----
3 4
8 5
7 1
4 5
------- test 12 ----
17 11
16 20
4 6
13 19
------- test 13 ----
4 2
2 6
2 3
5 8
------- test 14 ----
1 2
2 3
3 4
4 5
------- test 15 ----
4 8
8 12
12 16
16 20
------- test 16 ----
3 5
1 3
2 4
2 5
------- test 17 ----
4 3
4 4
6 3
5 5
------- test 18 ----
49 50
49 50
49 50
49 50
------- test 19 ----
10 50
45 30
28 38
36 20
------- test 20 ----
50 49
49 48
48 47
47 46
------- test 21 ----
50 49
48 47
46 45
45 44

Keep up the good work!


Thanks for your submission!

PROB The Clocks [ANALYSIS] ---- 这个题目也是够纠结的。

 

前期一直出现这个 RE

bad syscall #32000175 (RT_SIGPROCMASK) 
Your program printed data to stderr.  Here is the data:
          -------------------
          terminate_called_after_throwing_an_instance_of_'std::bad_alloc'
          __what():__std::bad_alloc
          -------------------
 

没办法,各种百度 google,终于有点头绪了,STL 的堆栈或者指针溢出或者出错了,但是和 stderr 有什么关系?求大牛各种解释!

//	solution 1:	BFS,
//			总共9种方法,不会全用,每个点最多4种状态,一共 4^9 种状态

/*
	solution 1
	data base: node
	status hash with (3 * 3 to int )
	{
	9 9 12		3 6 9 12
	6 6 6		1 2 3 4
	6 3 6		trans -> 334 222 212(int)
	9 ways :
	11011,111,110110,1001001,10111010,100100100,011011000,111000000,110110000
	}

	1	input
	2	search:
		for 9 - hash - expend();
	3	output;
*/

struct node {
	int step,way,pre;
	int mat;
	node(int a=0,int b=0,int c=0,int p=0):
	step(a),mat(b),way(c),pre(p){}
}first,nodetop,nodetmp;

hash_map<int,bool> has;

node que[MAXN];
int front =0,rear=0,kk=0,anss[100];
int expe[] = {0,110110000,111000000,11011000,100100100,10111010,1001001,110110,111,11011};

int hashi(int a[])
{
	int n=0;
	F(i,9) {
		switch(a[i]){

			case 3: n = n*10 + 1;break;
			case 6: n = n*10 + 2;break;
			case 9: n = n*10 + 3;break;
			case 12: n = n*10 + 4;break;

		}
	}
	return n;
}

int expend(int hx,int cas)
{
	int matt = hx + expe[cas],ans=0;
	int fuck[9]={0},i=0,matm = matt;
	while(matm)
	{
		fuck[i++] = matm%10;
		if(fuck[i-1] == 5) fuck[i-1]=1;
		matm /= 10;
	}
	ans += fuck[i-1];
	for(int j = i-2;j>=0;j--) {
		ans *= 10;
		ans += fuck[j];
	}
	return ans;
}

int bfs()
{
	/*
		init: hash表 队列

		取队头 - expend - hash判重 - 压入队列

	*/
	has.clear();
	//que.push_back(first);rear++;
	que[rear++] = first;
	while(front != rear) {
		nodetop = que[front++];
		if(nodetop.mat == 444444444) return nodetop.step;
		nodetmp.step = nodetop.step + 1;
		nodetmp.pre = front-1;
		//expend()
		FOR(i,1,9) {
			nodetmp.mat = expend(nodetop.mat,i);
			nodetmp.way = i;
			if(has.find(nodetmp.mat) == has.end()) {
				has[nodetmp.mat] = 1;
				//que.push_back(nodetmp);rear++;
				que[rear++] = nodetmp;
			}
		}
	}
	return 0;
}

void output(int depth)
{
	if(que[depth].pre != 0) {
		output(que[depth].pre);
	}
	anss[kk++] = que[depth].way;

	return ;
}

int main()
{
	FOPENTI
	FOPENTO
	kk=0;
	int a[9];
	F(i,9) SCF(a[i]);

	first=node(0,hashi(a),0,0);

	int de = bfs();
	if(de) {
		output(front-1);
		for(int i = 0;i<kk-1;i++){
			printf("%d ",anss[i]);
		}
		printf("%d\n",anss[kk-1]);
	}

}

不得不说,这个题目数据要求挺严格的,。

自勉一下

USER: Rain M [m3324631]
TASK: clocks
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.011 secs, 7876 KB]
   Test 2: TEST OK [0.011 secs, 7876 KB]
   Test 3: TEST OK [0.097 secs, 8608 KB]
   Test 4: TEST OK [0.162 secs, 9268 KB]
   Test 5: TEST OK [0.184 secs, 9532 KB]
   Test 6: TEST OK [0.475 secs, 11644 KB]
   Test 7: TEST OK [0.508 secs, 11908 KB]
   Test 8: TEST OK [0.529 secs, 11908 KB]
   Test 9: TEST OK [0.508 secs, 11908 KB]

All tests OK.
Your program ('clocks') produced all correct answers!  This is your
submission #10 for this problem.  Congratulations!

Here are the test data inputs:

------- test 1 ----
9 9 12
6 6 6
6 3 6
------- test 2 ----
12 9 12
9 9 9
12 9 12
------- test 3 ----
6 9 3
3 3 9
12 12 12
------- test 4 ----
9 3 9
9 9 9
9 9 9
------- test 5 ----
6 12 12
12 12 12
12 12 12
------- test 6 ----
3 12 9
6 6 6
12 12 12
------- test 7 ----
12 3 3
3 6 6
12 3 6
------- test 8 ----
12 3 9
9 12 12
3 6 9
------- test 9 ----
9 12 9
12 3 12
9 12 9
Keep up the good work!
Thanks for your submission

突然发现,这个section前后居然不是同一天,时差。。。ORZ

PROB Arithmetic Progressions [ANALYSIS] ----  这个题目很给力啊。

这个题目的关键就在定边界 和 倒着枚举等差的系数k

bool has[MAXN];

int n,m;

int cal(int a,int b,int k)
{
	return a + k * b;
}


int main()
{
	FOPENTI
	FOPENTO
	//FOPEN
	SCFD(n,m);
	FOR(i,0,m) FOR(j,0,m) {
		has[i*i + j*j] = 1;
	}
	n--;
 	bool flag = 1;
 	int upsum = 2 * m * m;
 	int upa = 2 * m * m - n + 1;
 	int upb = 2 * m * m / n;
 	FOR(b,1,upb) FOR(a,0,upa) {
 		if( cal(a,b,n) > upsum) continue;
 		bool isok = 1;
 		for(int k = n;k  >= 0;k--) {
 			int ans = cal(a,b,k);

 			if(!has[ans]){
 				isok = 0;
 				break;
 			}
 		}
	if(isok) printf("%d %d\n",a,b),flag = 0;
  	}
	if(flag) puts("NONE");

}
USER: Rain M [m3324631]
TASK: ariprog
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 3340 KB]
   Test 2: TEST OK [0.000 secs, 3340 KB]
   Test 3: TEST OK [0.000 secs, 3340 KB]
   Test 4: TEST OK [0.000 secs, 3340 KB]
   Test 5: TEST OK [0.022 secs, 3340 KB]
   Test 6: TEST OK [0.130 secs, 3340 KB]
   Test 7: TEST OK [1.490 secs, 3340 KB]
   Test 8: TEST OK [3.380 secs, 3340 KB]
   Test 9: TEST OK [2.981 secs, 3340 KB]

All tests OK.
Your program ('ariprog') produced all correct answers!  This is your
submission #4 for this problem.  Congratulations!

Here are the test data inputs:

------- test 1 ----
3
2
------- test 2 ----
5
7
------- test 3 ----
14
10
------- test 4 ----
10
13
------- test 5 ----
12
50
------- test 6 ----
18
100
------- test 7 ----
21
200
------- test 8 ----
22
250
------- test 9 ----
25
250
Keep up the good work!
Thanks for your submission!

晚上想想怎么证明这个稀疏关系。

PROB Mother's Milk [ANALYSIS] ---- 模拟一下,一开始没想到怎么模拟,仔细读题,发现了。

还有一个地方,就当 A 是0的时候记录 C 的容量是多少!。

//	solution 1	dfs
//	solution 2	DP maybe
/*
	solution 1
	1	select one ( no 0 )
	2	chose one to pull (if can't return)
	remeber all c
*/

map<int,int> mt;
map<int,int>::iterator p;
int has[22][22][22];//hash
int a[3];		//init
int tma[3]={0};		//statu

void dfs()
{

	for(int i = 0;i<3;i++){
		if(tma[i]) {
			for(int j = 0;j<3;j++) {
				if(i == j) continue;
				if(a[j] - tma[j]) {
					int botm = min(tma[i],a[j] - tma[j]);
					tma[i] -= botm;
					tma[j] += botm;
					if(!has[tma[0]][tma[1]][tma[2]]) {
						if(!tma[0])mt[tma[2]]=1;
						has[tma[0]][tma[1]][tma[2]] = 1;
						dfs();
					}
					tma[i] += botm;
					tma[j] -= botm;
				}
			}
		}
	}
	return;
}


int main()
{
	FOPENTI
	FOPENTO
	SET(has,0);mt.clear();
	SCFT(a[0],a[1],a[2]);
	tma[2]=a[2];
	has[0][0][a[2]]=1;mt[a[2]];
	dfs();
	p = mt.begin();
	printf("%d",p->first);
	p++;
	for(;p != mt.end();p++){
		printf(" %d",p->first);
	}
	puts("");
}

我没有让0输出,WA了一次。。。悲剧,不然用能看见first time congratulation等等了。。

USER: Rain M [m3324631]
TASK: milk3
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 3224 KB]
   Test 2: TEST OK [0.000 secs, 3224 KB]
   Test 3: TEST OK [0.000 secs, 3224 KB]
   Test 4: TEST OK [0.000 secs, 3224 KB]
   Test 5: TEST OK [0.000 secs, 3224 KB]
   Test 6: TEST OK [0.000 secs, 3224 KB]
   Test 7: TEST OK [0.000 secs, 3224 KB]
   Test 8: TEST OK [0.000 secs, 3224 KB]
   Test 9: TEST OK [0.000 secs, 3224 KB]
   Test 10: TEST OK [0.000 secs, 3224 KB]

All tests OK.
Your program ('milk3') produced all correct answers!  This is your
submission #2 for this problem.  Congratulations!

Here are the test data inputs:

------- test 1 ----
2 5 10
------- test 2 ----
20 20 20
------- test 3 ----
5 11 15
------- test 4 ----
2 12 20
------- test 5 ----
19 4 11
------- test 6 ----
5 11 13
------- test 7 ----
3 20 20
------- test 8 ----
7 16 20
------- test 9 ----
20 10 9
------- test 10 ----
7 12 18

Keep up the good work!


Thanks for your submission!

1.4 小结

这一节还是有很多值得做的题目,大都以深搜为主,模拟,或者枚举。

可以见得,很多题目都能用DP来做,是在是太神了,等这个chapter完事了回头看看给类DP。