炮兵阵地(acm.pku1185)解法

来源:互联网 发布:android 启动优化 编辑:程序博客网 时间:2024/06/04 23:37
炮兵阵地(acm.pku1185)解法与状态DP原理
 
# include <stdio.h># include <malloc.h>void Input(char*,int,int);void SetSolder(char*,int,int);void InitChoice(int*,char*,int,int);void FindBestPlace(int*,int,int,int);int Calculate(int*,int,int,int);void Connect(int*,int,int*,int,int);int main(int argc,char* argv[]){char *Map;//Map为地图数组int n,m;//n代表地图的高,m代表地图的宽printf("请输入地图的高度及宽度; ");scanf("%d %d",&n,&m);getchar();Map=(char*)malloc((n*m)*sizeof(char));printf("\n绘制地图,h表示山,p表示平原:\n");Input(Map,n,m);SetSolder(Map,n,m);free(Map);return 1;}void Input(char* Map,int n,int m){//用来对地图进行输入int i,j;printf("\n每行%d个字符,共计%d行\n",m,n); for(j=0;j<n;++j){for(i=0;i<m;++i)Map[j*m+i]=getchar(); getchar();}}void SetSolder(char *Map,int n,int m){//在平原上进行设置炮兵的函数,也是本程序的关键int *Choice,pi,num;//choice为选择数组名,平原初值为-1,在次平原上放炮兵其值为1,确定不在上放炮兵时为0Choice=(int*)malloc((n*m)*sizeof(int));InitChoice(Choice,Map,n,m);for(pi=0;pi<n*m;++pi)if(Choice[pi]==-1)FindBestPlace(Choice,pi,n,m);for(pi=0,num=0;pi<n*m;++pi)if(Choice[pi]==1) ++num;printf("\n\n最多可放人数: %d\n",num);free(Choice);}void InitChoice(int Choice[],char *Map,int n,int m){//用来初始化选择数组int Choice[],大小由输入的n*m值确定int pi;for(pi=0;pi<n*m;++pi)if(Map[pi]=='h') Choice[pi]=-2;else Choice[pi]=-1;}void FindBestPlace(int* Choice,int pi,int n,int m){//以平原pi为起点判断与之相连的平原选择哪一个int place[9],minnum=0,cout,pj,k,curpios=pi;minnum=Calculate(Choice,pi,n,m);if(minnum==0) Choice[pi]=1;else{Connect(Choice,pi,place,n,m); for(k=1;k<=place[0];++k){pj=place[k];cout=Calculate(Choice,pj,n,m); if(cout<minnum){curpios=pj;minnum=cout;}}if(curpios!=pi) Connect(Choice,curpios,place,n,m);Choice[curpios]=1;for(k=1;k<=place[0];++k){pj=place[k];Choice[pj]=0;}}}int Calculate(int* Choice,int pi,int n,int m){//计算射程范围内平原个数int num=0;int upone=pi-m,uptow=pi-2*m,downone=pi+m,downtow=pi+2*m,leftone=pi-1,lefttow=pi-2,rightone=pi+1,righttow=pi+2;if(upone>=0&&Choice[upone]==-1) ++num;if(uptow>=0&&Choice[uptow]==-1) ++num;if(downone<n*m&&Choice[downone]==-1) ++num;if(downtow<n*m&&Choice[downtow]==-1) ++num;if(pi%m!=0&&Choice[leftone]==-1) ++num;if(pi%m!=0&&leftone%m!=0&&Choice[lefttow]==-1) ++num;if(rightone%m!=0&&Choice[rightone]==-1) ++num;if((pi+1)%m!=0&&(rightone+1)%m!=0&&Choice[righttow]==-1) ++num;return num;}void Connect(int* Choice,int pi,int* place,int n,int m){//把相连的平原防入数组int i=0, upone=pi-m,uptow=pi-2*m,downone=pi+m,downtow=pi+2*m,leftone=pi-1,lefttow=pi-2,rightone=pi+1,righttow=pi+2; if(upone>=0&&Choice[upone]==-1) place[++i]=upone;if(uptow>=0&&Choice[uptow]==-1) place[++i]=uptow;if(downone<n*m&&Choice[downone]==-1) place[++i]=downone;if(downtow<n*m&&Choice[downtow]==-1) place[++i]=downtow;if(pi%m!=0&&Choice[leftone]==-1) place[++i]=leftone;if(pi%m!=0&&leftone%m!=0&&Choice[lefttow]==-1) place[++i]=lefttow;if(rightone%m!=0&&Choice[rightone]==-1) place[++i]=rightone;if((pi+1)%m!=0&&(rightone+1)%m!=0&&Choice[righttow]==-1) place[++i]=righttow; place[0]=i;}


 

原创粉丝点击