1 条题解
-
0
自动搬运
来自洛谷,原作者为

3493441984zz
**搬运于
2025-08-24 21:54:19,当前版本为作者最后更新于2018-10-27 09:06:06,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
纯粹模拟退火!!
感谢:我的好盆友:超級·考場WA怪帮我纠正了某些错误
题外话:
这道题其实比较好做的,
但是我用小号交了90遍才过不信可以去看,小号:模拟退火
开始
乱搞讲思路:1.按照题目要求先建一个有顺序的图,求出q
那样例打比方:
输入:
2 3 3
1 2 2
我们可以按照顺序建图
当然你也可以随机建图按顺序建图后为:
1 2 3 代码:
void getmap() { int x=1,y=1; for(int i=1;i<=c;i++) { while(color[i]--) { g[x][y]=i; nowg[x][y]=i; if(y==m) { x++; y=1; } else y++; } } }2.就可以开始
随意乱搞玄学模拟退火了如果对模拟退火不理解的话
不理解你也不会来这里吧,我推荐去看看2018年洛谷日报索引 里面的模拟退火算法如果没的话,就试试换换参数吧,我就是这样试过来的
下面贴没有剪枝但是开才了的代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #pragma GCC optimize(3) using namespace std; int g[25][25],color[55],nowg[25][25]; int n,m,c,ansq,older; int getq() { int sum=0; for(int i=1;i<n;i++) for(int j=1;j<m;j++) { if(nowg[i][j]!=nowg[i][j+1]) sum++; if(nowg[i][j]!=nowg[i+1][j]) sum++; } for(int i=1;i<m;i++) if(nowg[n][i]!=nowg[n][i+1]) sum++; for(int i=1;i<n;i++) if(nowg[i][m]!=nowg[i+1][m]) sum++; return sum; } void getmap() { int x=1,y=1; for(int i=1;i<=c;i++) { while(color[i]--) { g[x][y]=i; nowg[x][y]=i; if(y==m) { x++; y=1; } else y++; } } } void cpy() { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { // printf("%d ",nowg[i][j]); g[i][j]=nowg[i][j]; } //printf("\n"); } } void cpy1() { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { // printf("%d ",nowg[i][j]); nowg[i][j]=g[i][j]; } //printf("\n"); } } void monituihuo() { double T=1,deita=0.99999,T_min=1e-5; older=ansq; while(T>T_min) { int x1=(rand()%(n))+1; int y1=(rand()%(m))+1; int x2=(rand()%(n))+1; int y2=(rand()%(m))+1; int huan=nowg[x1][y1]; nowg[x1][y1]=nowg[x2][y2]; nowg[x2][y2]=huan; int ans_now=getq(); double de=ans_now-older; if((de<0)||(exp(-de/T)*RAND_MAX>((rand()%1000000)/1000000.0))) older=ans_now; else cpy1(); if(older<=ansq) { ansq=older; cpy(); } T*=deita; } } int main() { srand(107.77777777); srand(rand()); scanf("%d%d%d",&n,&m,&c); for(int i=1;i<=c;i++) scanf("%d",&color[i]); getmap(); ansq=getq(); older=ansq; /* for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) printf("%d ",nowg[i][j]); printf("\n"); }*/ for(int i=1;i<=3;i++) monituihuo(); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) printf("%d ",g[i][j]); cout<<endl; } //cout<<ansq<<endl; return 0; }如果觉得有用的话,让我看到你们的赞
- 1
信息
- ID
- 2896
- 时间
- 5000ms
- 内存
- 125MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者