思路:建立数据结构,录入数据内容,遍历着色,输出第一个可行的着色方案。
创新互联是一家企业级云计算解决方案提供商,超15年IDC数据中心运营经验。主营GPU显卡服务器,站群服务器,温江服务器托管,海外高防服务器,服务器机柜,动态拨号VPS,海外云手机,海外云服务器,海外服务器租用托管等。
下面就四个方面详细分析一下
首先分析数据结构:
对于地图,一个区块包含一个唯一编号数据(这个编号可以是地名,也可以是数字)用来区分该区块和其他区块的不同
另外要着色,还要考虑该区块和其他区块连接的情况
最后就是区块本身的颜色
通过上面的分析,即可建立如下数据结构:
struct area{
int nID;//这里以数字替代名称,作为地块的唯一标识
int nColor;//用1,2,3,4表示不同的颜色,用0表示还没有着色
area* pNei;//邻接的区块
int nNei;//邻接区块的数量
};
然后需要录入数据,这个请依据具体的地图进行处理,撰写相应的录入函数,填入上面的数据结构
假设录好的数据如下:
struct area city[64];//假设已经录制好了数据,初始所有城市颜色都为0
数据录好后,我们可以如下方式进行遍历,尝试着色
遍历分为个模块:一个是遍历模块,一个是校验模块
校验模块依序检查所有的城市和其邻接城市是否存在同色的情况,是则返回false,否则返回true
遍历模块则逐个城市进行上色尝试
可以考虑递归
下面给一个递归的示例:
检测模块:
bool isOk(){
for(int i=0;i64;i++)//假设有64个城市,其初始值和城市关系已经录制完毕
{
for(int j=0;jcity[i].nNei;j++){
if(nColor == city[i].pNei[j].nColor)
return false;
}
}
return true;
}
遍历递归模块:
bool addcity(int nIndex){
if(nIndex=64) return true;//所有城市都着色了,则返回成功
for(int i=1;i=4;i++){
city[nIndex].nColor=i;
if(isOk()){//本城市的颜色找到了
if(addcity(nIndex+1)==true){//找下一个城市的颜色
return true;
}else{//无法为下一个城市着色
continue;//更改本城市颜色
}
}
}
return false;//没有一个颜色可行,返回上一级,重新寻找
}
调用的时候可以采用下面的方式:
if(addcity(0)==false){
printf("无法找到答案,四色定理错误!\n");
}else{
printf("找到了答案,城市和着色结果如下:\n");
for(int i=0;i64;i++){
printf("city %03d color %d\n",city[i].nID,city[i].nColor);
}
}
IF函数一般是指Excel中的IF函数,根据指定的条件来判断其“真”(TRUE)、“假”(FALSE),根据逻辑计算的真假值,从而返回相应的内容。可以使用函数 IF 对数值和公式进行条件检测。
函数语法:
IF(logical_test,value_if_true,value_if_false)
Logical_test 表示计算结果为 TRUE 或 FALSE 的任意值或表达式。
例如,A10=100 就是一个逻辑表达式,如果单元格 A10 中的值等于 100,表达式即为 TRUE,否则为 FALSE。本参数可使用任何比较运算符(一个标记或符号,指定表达式内执行的计算的类型。有数学、比较、逻辑和引用运算符等。)。
Value_if_true logical_test 为 TRUE 时返回的值。
例如,如果本参数为文本字符串“预算内”而且 logical_test 参数值为 TRUE,则 IF 函数将显示文本“预算内”。如果 logical_test 为 TRUE 而 value_if_true 为空,则本参数返回 0(零)。如果要显示 TRUE,则请为本参数使用逻辑值 TRUE。value_if_true 也可以是其他公式。
Value_if_false logical_test 为 FALSE 时返回的值。
例如,如果本参数为文本字符串“超出预算”而且 logical_test 参数值为 FALSE,则 IF 函数将显示文本“超出预算”。如果 logical_test 为 FALSE 且忽略了 value_if_false(即 value_if_true 后没有逗号),则会返回逻辑值 FALSE。如果 logical_test 为 FALSE 且 value_if_false 为空(即 value_if_true 后有逗号,并紧跟着右括号),则本参数返回 0(零)。VALUE_if_false 也可以是其他公式。
说明:
·在EXCEL2003中 函数 IF 可以嵌套七层,在EXCEL2007中可以嵌套256层,用 value_if_false 及 value_if_true 参数可以构造复杂的检测条件。
· 在计算参数 value_if_true 和 value_if_false 后,函数 IF 返回相应语句执行后的返回值。
· 如果函数 IF 的参数包含数组( 用于建立可生成多个结果或可对在行和列中排列的一组参数进行运算的单个公式。数组区域共用一个公式;数组常量是用作参数的一组常量),则在执行 IF 语句时,数组中的每一个元素都将计算。
· WPS表格 还提供了其他一些函数,可依据条件来分析数据。例如,如果要计算单元格区域中某个文本字符串或数字出现的次数,则可使用 COUNTIf 工作表函数。如果要根据单元格区域中的某一文本字符串或数字求和,则可使用 SUMIf 工作表函数。请了解关于根据条件计算值。
·如果判断标准有汉字内容,则在汉字前后加上英文状态下的双引号""G2
(例如:IF(G2="成都",400,200))
函数示例:
1 数据
2 50
公式:=IF(A2=100,"Withinbudget","Overbudget")
说明(结果):如果上面的数字小于等于100,则公式将显示“Withinbudget”。否则,公式显示“Overbudget”。(Withinbudget)
公式:=IF(A2=100,SUM(B5:B15),"")
说明(结果):如果上面数字为100,则计算单元格区域B5:B15,否则返回空文本("")
从一个省开始,给它涂上任意一种颜色1,遍历它旁边的省份,涂上与已经涂色并于他相邻的省份不同的颜色就行了。
理论上4种颜色就够了.地图的四色问题嘛!
可能会有多组解。用递归(dfs)就可以输出所有解了。
地图着色算法C语言源代码
前面我写了一个地图着色(即四色原理)的C源代码。
写完以后想了一下,感觉还不完善,因为从实际操作的角度来考虑,四种可用的颜色放在旁边,不同的人可能会有不同的选择顺序,另外,不同的人可能会选择不同的城市作为着色的起点,而当时的程序没有考虑这个问题。于是,把程序修改为下面的样子,还请同行分析并指出代码中的不足之处:
#i nclude stdio.h
#define N 21
int allcolor[4];/*可用的颜色*/
int ok(int metro[N][N],int r_color[N],int current)
{/*ok函数和下面的go函数和原来的一样,保留用来比较两种算法*/
int j;
for(j=1;jcurrent;j++)
if(metro[current][j]==1r_color[j]==r_color[current])
return 0;
return 1;
}
void go(int metro[N][N],int r_color[N],int sum,int current)
{
int i;
if(current=sum)
for(i=1;i=4;i++)
{
r_color[current]=i;
if(ok(metro,r_color,current))
{
go(metro,r_color,sum,current+1);
return;
}
}
}
void color(int metro[N][N],int r_color[N],int sum,int start)
{
int i,j,k;
r_color=allcolor[0];
for(i=start+1;i!=start;i=(i+1)%(sum+1))/*把所有编号看作一个环*/
if(i==0)/*城市号从1开始编号,故跳过0编号*/
continue;
else
for(j=0;j4;j++)
{
r_color[i]=allcolor[j];/*选取下一种颜色,根据allcolor中颜色顺序不同,结果不同*/
for(k=1;ki;k++)/*检查是否有冲突,感觉还可以改进,如使用禁忌搜索法*/
if(metro[i][k]==1r_color[k]==r_color[i])
break;
if(k=i)
break;
}
}
void main()
{
int r_color[N]={0};
int t_color[N]={0};
int i;
int start;/*着色的起点*/
int metro[N][N]={{0},
{0,1,1,1,1,1,1},
{0,1,1,1,1},
{0,1,1,1,0,0,1},
{0,1,1,0,1,1},
{0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0,1},
{0,1,0,1,0,1,1,1,1,1},
{0,0,0,0,0,0,1,1,1},
{0,0,0,0,0,0,1,1,1,1,0,0,1},
{0,0,0,0,0,1,1,0,1,1,0,0,1,1,1,0,1},
{0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,1,0,0,0,1},
{0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1},
{0,0,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0,0,0,1,1},
{0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,1,0,1},
{0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1},
{0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,1,1},
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1}};
allcolor[0]=1;allcolor[1]=2;allcolor[2]=3;allcolor[3]=4;/*选色顺序,顺序不同,结果不同*/
start=1;
/* clrscr();*/
printf("\nAll color is:\n");
for(i=0;i4;i++)/*当前选色顺序*/
printf("%d ",allcolor[i]);
go(metro,r_color,20,1);
printf("\nFirst method:\n");
for(i=1;i=20;i++)
printf("%3d",r_color[i]);
color(metro,t_color,20,start);
printf("\nSecond method:\n");
printf("\nAnd the start metro is:%d\n",start);
for(i=1;i=20;i++)
printf("%3d",t_color[i]);
}
说是人性化着色,其实还有一个问题没有考虑,那就是操作员跳跃式着色,就像大家玩“扫雷”游戏一样。其实也容易实现,可以像定义选色顺序一样定义着色顺序。
#include stdio.h
int max(int a,int b,int c);
int min(int a,int b,int c);
void main()
{
int x,y,z;
printf("请输入三个数:");
scanf("%d%d%d",x,y,z);
printf("三个数选出最大数是%d\n",max(x,y,z));
printf("三个数选出最小数是%d\n",min(x,y,z));
}
int max(int a,int b,int c)
{
if (a=ba=c)
return a;
if (b=ab=c)
return b;
else
return c;
}
int min(int a,int b,int c)
{
if (a=ba=c)
return a;
if (b=ab=c)
return b;
else
return c;
}