user-0 提问: 求问个算法问题，题目如下

回复:
user: user-1
content: if (res < ans) res = ans;//?????

user: user-2
content: 引用 37 楼 super_miker 的回复:位运算+记忆化搜索 核心代码：   int mask[20] = {    0x00012, 0x00025, 0x0004A, 0x00084,    0x00121, 0x00252, 0x004A4, 0x00848,    0x01210, 0x02520, 0x04A40, 0x08480,    0x12100, 0x25200, 0x4A400, 0x84800,    0x21000, 0x52000, 0xA4000, 0x48000, }; int memory[1<<20]; memset(memory, -1, sizeof(memory)); memory[0] = 0; int dfs(int code){    if (memory[code] >= 0) return memory[code];    else{       int ans = INT_MAX;       for (int i = 0; i < 20; ++i){          if ((code & 1 << i) == 0 && (code & mask[i]) != 0){             int res = dfs(code & ~mask[i]);             if (res < ans) res = ans;          }       }       return memory[code] = ans;    } }  1	213443	cfltdf	------	------	C	------	2015-04-10 16:20:58 已过

user: user-2
content: 位运算+记忆化搜索 核心代码：   int mask[20] = {    0x00012, 0x00025, 0x0004A, 0x00084,    0x00121, 0x00252, 0x004A4, 0x00848,    0x01210, 0x02520, 0x04A40, 0x08480,    0x12100, 0x25200, 0x4A400, 0x84800,    0x21000, 0x52000, 0xA4000, 0x48000, }; int memory[1<<20]; memset(memory, -1, sizeof(memory)); memory[0] = 0; int dfs(int code){    if (memory[code] >= 0) return memory[code];    else{       int ans = INT_MAX;       for (int i = 0; i < 20; ++i){          if ((code & 1 << i) == 0 && (code & mask[i]) != 0){             int res = dfs(code & ~mask[i]);             if (res < ans) res = ans;          }       }       return memory[code] = ans;    } }

user: user-3
content: 内存限制居然有32M。。这样的话2^20=1048576，直接生成一个表然后每次查表速度不能再快。。

user: user-1
content: 引用 34 楼 dooX8086 的回复:[quote=引用 32 楼 zhao4zhong1 的回复:] 26楼代码正确。   15楼代码有Bug！   这种取巧的方法是错的[/quote] 多费几颗炸弹，还能提振军工业呢！

user: user-4
content: 引用 32 楼 zhao4zhong1 的回复:26楼代码正确。   15楼代码有Bug！   这种取巧的方法是错的

user: user-5
content: Ada不喜欢学数字,却喜欢玩游戏,看着她的小手指在手机屏上戳来戳去,顿时感觉祖国的游戏事业有了未来.

user: user-1
content: 26楼代码正确。   15楼代码有Bug！

user: user-1
content: 引用 30 楼 my_bkb 的回复:[quote=引用 29 楼 zhao4zhong1 的回复:] “给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出 内个 对于调试我有个问 全局数组 还有传入函数的数组 在调试时无法显示各成员数值怎么办啊[/quote] 自己写一小段代码或一个函数，显示你想看的数据结构，例如： //带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

user: user-0
content: 引用 29 楼 zhao4zhong1 的回复:“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出 内个 对于调试我有个问 全局数组 还有传入函数的数组 在调试时无法显示各成员数值怎么办啊

user: user-1
content: “给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出

user: user-1
content: 引用 26 楼 my_bkb 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 保存现场 测试下一个1旁边的0 模拟爆炸 若全0，记录本轮共炸几次，恢复现场，递归 若非全0，递归 这段代码是我一朋友写的 过了 还挺简便的 可是看不懂  #include<iostream> #include<cstdio> using namespace std; #define MAXN 1<<20 const int MASK=(1<<20)-1; char str[1000]; int ans[MAXN]; int dfs(int pos){     if(ans[pos]!=MAXN) return ans[pos];     int rt = MAXN;     for(int i=0;i<20;i++){         if( pos&1<<i ){             if( i>3 && ( (pos&1<<(i-4))==0) ) {                 int boom = i-4 ,newpos = pos & ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i<16 && ( (pos&1<<(i+4))==0) ) {                 int boom = i+4 ,newpos = pos & ~(1<<i);                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i%4!=0 && ( (pos&1<<(i-1))==0) ) {                 int boom = i-1 ,newpos = pos& ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i%4!=3 && ( (pos&1<<(i+1))==0) ) {                 int boom = i+1 ,newpos = pos& ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }         }     }     return ans[pos]=rt; } int main(){     int case_cnt=1;     for(int i=1;i<MAXN;i++){         ans[i]=MAXN;     }     ans[0]=0;     while(gets(str)){         int tmp=0,tmpcnt=1;         for(int i=0;i<5;i++){             gets(str);             for(int j=0;j<4;j++){                 if(str[j]=='1') tmp+=tmpcnt;                 tmpcnt<<=1;             }         }         //printf("tmp=%d\n",tmp);         printf("The result of case %d is %d\n",case_cnt++,dfs(tmp));     }     return 0; }[/quote] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

user: user-1
content: 22楼再试试这个： Case 1: 1100 0100 1010 0100 0010

user: user-0
content: 引用 1 楼 zhao4zhong1 的回复:保存现场 测试下一个1旁边的0 模拟爆炸 若全0，记录本轮共炸几次，恢复现场，递归 若非全0，递归 这段代码是我一朋友写的 过了 还挺简便的 可是看不懂  #include<iostream> #include<cstdio> using namespace std; #define MAXN 1<<20 const int MASK=(1<<20)-1; char str[1000]; int ans[MAXN]; int dfs(int pos){     if(ans[pos]!=MAXN) return ans[pos];     int rt = MAXN;     for(int i=0;i<20;i++){         if( pos&1<<i ){             if( i>3 && ( (pos&1<<(i-4))==0) ) {                 int boom = i-4 ,newpos = pos & ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i<16 && ( (pos&1<<(i+4))==0) ) {                 int boom = i+4 ,newpos = pos & ~(1<<i);                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i%4!=0 && ( (pos&1<<(i-1))==0) ) {                 int boom = i-1 ,newpos = pos& ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=0 ) newpos &= ~(1<<(boom-1));                 rt = min( rt , dfs(newpos)+1 );             }             if( i%4!=3 && ( (pos&1<<(i+1))==0) ) {                 int boom = i+1 ,newpos = pos& ~(1<<i);                 if( boom > 3 ) newpos &= ~(1<<(boom-4));                 if( boom < 16 ) newpos &= ~(1<<(boom+4));                 if( boom%4!=3 ) newpos &= ~(1<<(boom+1));                 rt = min( rt , dfs(newpos)+1 );             }         }     }     return ans[pos]=rt; } int main(){     int case_cnt=1;     for(int i=1;i<MAXN;i++){         ans[i]=MAXN;     }     ans[0]=0;     while(gets(str)){         int tmp=0,tmpcnt=1;         for(int i=0;i<5;i++){             gets(str);             for(int j=0;j<4;j++){                 if(str[j]=='1') tmp+=tmpcnt;                 tmpcnt<<=1;             }         }         //printf("tmp=%d\n",tmp);         printf("The result of case %d is %d\n",case_cnt++,dfs(tmp));     }     return 0; }

user: user-0
content: 引用 16 楼 zhao4zhong1 的回复: 这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。 喜欢这句话

user: user-1
content: 22楼试试这个： Case 1: 1111 0101 0101 1101 1001

user: user-1
content: 这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。

user: user-6
content: 引用 16 楼 zhao4zhong1 的回复: 这个世界上最大的差别和最远的距离都存在于“说”和“做”之间。 严重同意！ 比如建筑师和搬砖的！ apple 和富士康

user: user-4
content: 1 计算格子权值（0的上下左右有多少个1 -- 障碍物) 2 在权值最大的格子放 炸弹 （清除四个相邻格的障碍物） 3 --- loop --> 1  (直到所有格子为0)  ================================ 应该可以秒杀 如果去除IO部份时间应该毫秒级别完成， 如加上IO时间，估算一下都没有1M数据，也应该在1秒内完成

user: user-4
content: 引用 13 楼 dooX8086 的回复:1 计算格子权值（0的上下左右有多少个1 -- 障碍物) 2 在权值最大的格子放 炸弹 （清除四个相邻格的障碍物） 3 --- loop --> 1  (直到所有格子为0)  ================================ 应该可以秒杀 如果去除IO部份时间应该毫秒级别完成， 如加上IO时间，估算一下都没有1M数据，也应该在1秒内完成   ////////=========================================================== 测试数据   结果     #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h>   #define MAP_ROW 5 #define MAP_COL 4   #define RES_0 '0' #define RES_1 '1'   typedef char map_t[MAP_ROW][MAP_COL]; typedef char byte;   typedef struct { 	byte row, col; 	byte val; } mpos_t;    int is_vaild(byte row, byte col) { 	return 0 <= row && row < MAP_ROW && 0 <= col && col < MAP_COL; }   void bomb_out(map_t map, byte row, byte col) { 	if ( is_vaild(row + 1, col) ) map[row + 1][col] = RES_0; 	if ( is_vaild(row, col + 1) ) map[row][col + 1] = RES_0; 	if ( is_vaild(row - 1, col) ) map[row - 1][col] = RES_0;  	if ( is_vaild(row, col - 1) ) map[row][col - 1] = RES_0; }   // 计算权值 int calc_val(map_t map, byte row, byte col) { 	return (is_vaild(row + 1, col) && RES_1 == map[row + 1][col]) 		 + (is_vaild(row, col + 1) && RES_1 == map[row][col + 1]) 		 + (is_vaild(row - 1, col) && RES_1 == map[row - 1][col]) 		 + (is_vaild(row, col - 1) && RES_1 == map[row][col - 1]); }   // 查找权值最大的格子 void find_max_mpv(map_t map, mpos_t *mpos) { 	byte val; 	memset(mpos, 0x0, sizeof(mpos_t)); 	for (int row=0; row < MAP_ROW; ++row) { 		for (int col=0; col < MAP_COL; ++col) { 			if (RES_0 == map[row][col]) { 				val = calc_val(map, row, col); 				if (mpos->val < val) { 					mpos->val = val; 					mpos->row = row; 					mpos->col = col;  					if (4 == mpos->val) return ;		// 权值4 已是最大了,不用再找 				} 			} 		} 	} }    void generate_test_data(int num) { 	srand( time(NULL) ); 	char buf[MAP_ROW * MAP_COL] = {0}; 	for (int id=1; id<=num; ++id) {  		memset(buf, RES_0, MAP_ROW * MAP_COL);  		int bc = 1 + rand() % 18; 		memset(buf, RES_1, bc);  		printf("Case %d:\n", id); 		 		int tmp; 		for (int bit=0; bit<MAP_ROW * MAP_COL; ++bit) { 			int i = rand() % MAP_ROW * MAP_COL; 			tmp = buf[i]; 			buf[i] = buf[bit]; 			buf[bit] = tmp; 		}  		for (int row=0; row < MAP_ROW; ++row) printf("%.4s\n", buf + row * MAP_COL); 	}  }  int main(int argc, char *argv[]) { 	// generate test data 	//generate_test_data(20000); 	//exit(0);  	// 数据测试  	if (2 <= argc) 		freopen(argv[1], "r", stdin);  	if (3 == argc) 		freopen(argv[2], "w", stdout);  	clock_t start_time, end_time; 	start_time = clock();  	 	char buf[64]; 	int id = 0; 	map_t map; 		 	for(;;) 	{ 		// ------------------------------ 		// 输入数据 		// 		if (EOF == fscanf(stdin, "%*[^\n] ") ) break;  		++id; 		//printf("-- case %d ---\n", id); 		for (int row=0; row < MAP_ROW; ++row) { 			fgets(buf, 64, stdin); 			memcpy(map[row], buf, MAP_COL); 			//printf("%.4s\n", map[row]); 		} 		 		// -------------------------------- 		// 处理 		// 		mpos_t mpos = {0}; 		int bomb_count = {0}; 		 		for (find_max_mpv(map, &mpos); 0 < mpos.val; find_max_mpv(map, &mpos)) { 			++bomb_count; 			bomb_out(map, mpos.row, mpos.col); 		}  		// ------------------------------- 		// 输出 		// 		fprintf(stdout, "the result of case %d is %d\n", id, bomb_count); 	}	  	end_time = clock();  	fprintf(stdout, "\ntime:%f second\n", (double)(end_time - start_time) / CLOCKS_PER_SEC);  	return 0; }