Warning: session_start(): open(/tmp/sess_27fe7f2e216576022c874099c42be9fd, O_RDWR) failed: No space left on device (28) in /data/wiki/inc/init.php on line 239

Warning: session_start(): Failed to read session data: files (path: ) in /data/wiki/inc/init.php on line 239

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/auth.php on line 430
Writing /data/wiki/data/cache/8/8fe637ac40e9dfa91f93fbcd08d065e4.captchaip failed

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/actions.php on line 38

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/lib/tpl/dokuwiki/main.php on line 12
2020-2021:teams:bigbros:jerydeak:sps1 [CVBB ACM Team]

用户工具

站点工具


2020-2021:teams:bigbros:jerydeak:sps1

Single Problem Set (1)


1.方格取数

  • Date: 2020/5/12
  • Tag: DP
  • Problem: 设有 N × N 的方格图 (N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 0。某人从图的左上角的 A 点出发,可以向下行走,也可以向右走,直到到达右下角的 B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字00)。此人从 A 点到 B 点共走两次,试找出 2 条这样的路径,使得取得的数之和为最大。
  • Solution: 不妨两次同时走,则两次总步数是相同的,只需要用 ans[step][x1][x2] 存储“步数为step,第一、二次行动的横坐标分别为 x1,x2 ”时的最优解,递归即可。

Code

Code

#include<stdio.h>
#include<string.h>
#define condition(con,tr,fa) ((con)?(tr):(fa))
#define max(a,b) condition(a>b,a,b)
#define min(a,b) condition(a<b,a,b)
#define reset(arr) memset(arr,0,sizeof(arr))
 
int map[10][10];
int ans[20][10][10];
int ansflag[20][10][10];
int n;
 
int ansf(int step,int x1,int x2){
	if(step==0)return map[0][0];
	if(ansflag[step][x1][x2]>0){
		return ans[step][x1][x2];
	}
	int y1=step-x1;
	int y2=step-x2;
 
	int temp=0;
	if(x1>0 && x2>0) temp=max(temp,ansf(step-1,x1-1,x2-1));
	if(x1>0 && y2>0) temp=max(temp,ansf(step-1,x1-1,x2));
	if(y1>0 && x2>0) temp=max(temp,ansf(step-1,x1,x2-1));
	if(y1>0 && y2>0) temp=max(temp,ansf(step-1,x1,x2));
	ans[step][x1][x2]=temp+map[x1][y1]+map[x2][y2]*condition(x1==x2,0,1);
	ansflag[step][x1][x2]=1;
 
	return ans[step][x1][x2];
}
 
int main(){
	reset(map);
	reset(ans);
	reset(ansflag);
 
	scanf(%d”,&n);
 
	int x,y,val=1;
	while(x!=0 || y!=0 || val!=0){
		scanf(%d%d%d”,&x,&y,&val);
		map[x-1][y-1]=val;
	}
	/*
	printf(“\n”);
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			printf(%d ”,map[i][j]);
		}
		printf(“\n”);
	}printf(“\n”);
	*/
 
	printf(%d”,ansf(n*2-2,n-1,n-1));
}

2.传纸条

  • Date: 2020/5/14
  • Tag: DP
  • Problem: 设有 M × N 的方格图 (M, N≤50),所有方格填入非负整数;其中,保证左上右下为0。从左上到右下选择两条路径,每条必须满足要么向右要么向下,且两条不能有交叉。求路径数字之和最大值。
  • Solution: 解类似1,不过在递归时,取消了 x1-1==x2-1 一项。另外,需要注意的是,多维数组不要忘了哪个分量为行或者列。

Code

Code

#include<stdio.h>
#include<string.h>
#define condition(con,tr,fa) ((con)?(tr):(fa))
#define max(a,b) condition(a>b,a,b)
#define min(a,b) condition(a<b,a,b)
#define reset(arr) memset(arr,0,sizeof(arr))
 
#define MAXN 51
 
int map[MAXN][MAXN];
int ans[MAXN+MAXN][MAXN][MAXN];
int ansflag[MAXN+MAXN][MAXN][MAXN];
int m,n;
 
 
int ansf(int step,int x1,int x2){
	//printf(“\nCall:step=%d,x1=%d,x2=%d;\n”,step,x1,x2);
	if(step==0)return map[0][0];
	if(ansflag[step][x1][x2]>0){
		return ans[step][x1][x2];
	}
	int y1=step-x1;
	int y2=step-x2;
 
	int temp=0;
	if(x1>0 && x2>0 && x1-1!=x2-1) temp=max(temp,ansf(step-1,x1-1,x2-1));
	if(x1>0 && y2>0 && x1-1!=x2) temp=max(temp,ansf(step-1,x1-1,x2));
	if(y1>0 && x2>0 && x1!=x2-1) temp=max(temp,ansf(step-1,x1,x2-1));
	if(y1>0 && y2>0 && x1!=x2) temp=max(temp,ansf(step-1,x1,x2));
 
	//printf(“\nPoint 1:step=%d,x1=%d,x2=%d;temp=%d;map1=%d,map2=%d;\n”,step,x1,x2,temp,map[x1][y1],map[x2][y2]);
	ans[step][x1][x2]=temp+map[y1][x1]+map[y2][x2];//*condition(x1==x2,0,1);
	ansflag[step][x1][x2]=1;
 
	//printf(“\nAfter calculating:step=%d,x1=%d,x2=%d;Value=%d;\n”,step,x1,x2,ans[step][x1][x2]);
	return ans[step][x1][x2];
}
 
int main(){
	reset(map);
	reset(ans);
	reset(ansflag);
 
	scanf(%d%d”,&m,&n);
 
	int x,y,val=1;
	for(int i=0;i<m;i++)
	for(int j=0;j<n;j++)
		scanf(%d”,&map[i][j]);
 
	/*
	printf(“\n”);
	for(int i=0;i<m;i++){
		for(int j=0;j<n;j++){
			printf(%d ”,map[i][j]);
		}
		printf(“\n”);
	}printf(“\n”);
	*/
	printf(%d”,ansf(m+n-2,n-1,n-1));
 
	/*
	for(int step=0;step<m+n-1;step++){
		printf(“\n—–\nStep=%d:\n”,step);
		for(int x1=0;x1<n;x1++){
			printf(“\n”);
			for(int x2=0;x2<n;x2++){
				printf(%d ”,ans[step][x1][x2]);
			}
		}
	}
	*/
	/*
	while(true){
		printf(“\n————–\n”);
		char c;
		scanf(%c”,&c);
		if(c=='a'){
			int step,x1,x2;
		scanf(%d%d%d”,&step,&x1,&x2);
		//printf(%d\n”,ansf(step,x1,x2));
		printf(%d\n”,ans[step][x1][x2]);
		printf(“\n————–\n”);
		}
		else if(c=='m'){
			int x,y;
		scanf(%d%d”,&x,&y);
		printf(%d\n”,map[x][y]);
		printf(“\n————–\n”);
 
		}
	}*/
}
2020-2021/teams/bigbros/jerydeak/sps1.1589718030.txt.gz · 最后更改: 2020/05/17 20:20 由 jerydeak