• [UOJ#404][CTSC2018]组合数问题(79分,提交答案题,模拟退火+匈牙利+DP)


    1、4、5、6、10都是op=1的点,除4外直接通过模拟退火调参可以全部通过。

     1 #include<cmath>
     2 #include<ctime>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     7 using namespace std;
     8 
     9 const int N=5010;
    10 int n,m,K,op,ans,u,v,t[N][N],r[N][N],pos[N];
    11 struct E{ int u,v; }e[N];
    12 
    13 int sj(int l,int r){ return rand()%(r-l+1)+l; }
    14 double Rand(){ return sj(0,10000)/10000.; }
    15 
    16 int calc(){
    17     int res=0;
    18     rep(i,1,n) res+=t[i][pos[i]];
    19     rep(i,1,m) res+=r[pos[e[i].u]][pos[e[i].v]];
    20     return res;
    21 }
    22 
    23 void SA(){
    24     for (double T=1e30; T>0.001; T*=0.99997){
    25         int p=sj(1,n),q=sj(1,K),ans1=ans-t[p][pos[p]]+t[p][q];
    26         rep(i,1,m){
    27             if (e[i].u==p) ans1=ans1-r[pos[p]][pos[e[i].v]]+r[q][pos[e[i].v]];
    28             if (e[i].v==p) ans1=ans1-r[pos[e[i].u]][pos[p]]+r[pos[e[i].u]][q];
    29         }
    30         int delta=ans-ans1;
    31         if (delta>0 || Rand()<exp(delta/T)) ans=ans1,pos[p]=q;
    32     }
    33     rep(i,1,1000){
    34         int p=sj(1,n),q=sj(1,K),ans1=ans-t[p][pos[p]]+t[p][q];
    35         rep(i,1,m){
    36             if (e[i].u==p) ans1=ans1-r[pos[p]][pos[e[i].v]]+r[q][pos[e[i].v]];
    37             if (e[i].v==p) ans1=ans1-r[pos[e[i].u]][pos[p]]+r[pos[e[i].u]][q];
    38         }
    39         if (ans>ans1) ans=ans1,pos[p]=q;
    40     }
    41 }
    42 
    43 int main(){
    44     freopen("placement5.in","r",stdin);
    45     freopen("placement5.out","w",stdout);
    46     srand(time(0));
    47     scanf("%d%d%d%d",&n,&m,&K,&op);
    48     rep(i,1,m) scanf("%d%d",&u,&v),e[i]=(E){u,v};
    49     rep(i,1,n) rep(j,1,K) scanf("%d",&t[i][j]);
    50     rep(i,1,K) rep(j,1,K) scanf("%d",&r[i][j]);
    51     rep(i,1,n) pos[i]=1; ans=calc(); SA();
    52     rep(i,1,n) printf("%d ",pos[i]); puts("");
    53     return 0;
    54 }
    View Code

    4号点是[1,133],[134,266],[267,399]三条链,做三次同样的DP即可。

     1 #include<cmath>
     2 #include<ctime>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     7 using namespace std;
     8 
     9 const int N=5010,inf=1e9;
    10 int n,m,K,op,ans,id,u,v,t[N][N],r[N][N],pre[N][N],f[N][N];
    11 
    12 void Print(int l,int i,int j){ if (i>l) Print(l,i-1,pre[i][j]); printf("%d ",j); }
    13 
    14 int main(){
    15     freopen("placement4.in","r",stdin);
    16     freopen("placement4.out","w",stdout);
    17     srand(time(0));
    18     scanf("%d%d%d%d",&n,&m,&K,&op);
    19     rep(i,1,m) scanf("%d%d",&u,&v);
    20     rep(i,1,n) rep(j,1,K) scanf("%d",&t[i][j]);
    21     rep(i,1,K) rep(j,1,K) scanf("%d",&r[i][j]);
    22     rep(i,1,n) rep(j,1,K) f[i][j]=inf;
    23     rep(i,1,133) rep(j,1,K)
    24         rep(k,1,K){
    25             int s=f[i-1][k]+r[k][j]+t[i][j];
    26             if (s<f[i][j]) f[i][j]=s,pre[i][j]=k;
    27         }
    28     ans=inf;
    29     rep(i,1,K) if (f[133][i]<ans) ans=f[133][i],id=i;
    30     Print(1,133,id);
    31     rep(i,1,K) f[134][i]=t[134][i];
    32     rep(i,134,266) rep(j,1,K)
    33         rep(k,1,K){
    34             int s=f[i-1][k]+r[k][j]+t[i][j];
    35             if (s<f[i][j]) f[i][j]=s,pre[i][j]=k;
    36         }
    37     ans=inf;
    38     rep(i,1,K) if (f[266][i]<ans) ans=f[266][i],id=i;
    39     Print(134,266,id);
    40     rep(i,1,K) f[267][i]=t[267][i];
    41     rep(i,267,399) rep(j,1,K)
    42         rep(k,1,K){
    43             int s=f[i-1][k]+r[k][j]+t[i][j];
    44             if (s<f[i][j]) f[i][j]=s,pre[i][j]=k;
    45         }
    46     ans=inf;
    47     rep(i,1,K) if (f[399][i]<ans) ans=f[399][i],id=i;
    48     Print(267,399,id);
    49     return 0;
    50 }
    View Code

    2、3、8、9同样可以用模拟退火做,发现题目给的simulator会创建一个rex.txt来存放op=2时的答案,于是直接用它做估价函数即可。这样第二个点可以得到满分,第3个点可以得到3分,第8个点可以得到1分,第9个点可以得到5分。

     1 #include<cmath>
     2 #include<ctime>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<iostream>
     6 #include<algorithm>
     7 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     8 using namespace std;
     9 
    10 const int N=5010;
    11 int n,m,K,op,ans,u,v,t[N][N],r[N][N],pos[N];
    12 struct E{ int u,v; }e[N*N];
    13 
    14 int sj(int l,int r){ return rand()%(r-l+1)+l; }
    15 double Rand(){ return sj(0,10000)/10000.; }
    16 
    17 int calc(){
    18     freopen("placement9.out","w",stdout);
    19     rep(i,1,n) printf("%d ",pos[i]); puts("");
    20     fclose(stdout);
    21     system("./simulator placement9.in placement9.out");
    22     freopen("res.txt","r",stdin);
    23     int res; scanf("%d",&res); fclose(stdin); return res;
    24 }
    25 
    26 void SA(){
    27     for (double T=1e10; T>0.001; T*=0.997,cerr<<T<<endl){
    28         int p=sj(1,n),q=sj(1,K),w=pos[p]; pos[p]=q;
    29         int ans1=calc(),delta=ans-ans1;
    30         if (delta>0 || Rand()<exp(delta/T)) ans=ans1; else pos[p]=w;
    31     }
    32     rep(i,1,1000){
    33         int p=sj(1,n),q=sj(1,K),w=pos[p]; pos[p]=q;
    34         int ans1=calc();
    35         if (ans>ans1) ans=ans1; else pos[p]=w;
    36     }
    37 }
    38 
    39 int main(){
    40     freopen("placement9.in","r",stdin);
    41     srand(time(0));
    42     scanf("%d%d%d%d",&n,&m,&K,&op);
    43     rep(i,1,m) scanf("%d%d",&u,&v),e[i]=(E){u,v};
    44     rep(i,1,n) rep(j,1,K) scanf("%d",&t[i][j]);
    45     rep(i,1,K) rep(j,1,K) scanf("%d",&r[i][j]);
    46     rep(i,1,n) pos[i]=1; ans=calc(); SA();
    47     freopen("placement9.out","w",stdout);
    48     rep(i,1,n) printf("%d ",pos[i]); puts("");
    49     return 0;
    50 }
    View Code

    7号点可以直接跑匈牙利得到结果。

     1 #include<cmath>
     2 #include<ctime>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     7 using namespace std;
     8 
     9 const int N=5010;
    10 int n,m,K,op,u,v,vis[N],lnk[N],ans[N],t[N][N],r[N][N],pos[N];
    11 
    12 bool work(int x,int p){
    13     rep(i,1,K) if (t[x][i]<=1014 && vis[i]!=p){
    14         vis[i]=p;
    15         if (lnk[i]==-1 || work(lnk[i],p)){ lnk[i]=x; return 1; }
    16     }
    17     return 0;
    18 }
    19 
    20 int main(){
    21     freopen("placement7.in","r",stdin);
    22     freopen("placement7.out","w",stdout);
    23     srand(time(0));
    24     scanf("%d%d%d%d",&n,&m,&K,&op);
    25     rep(i,1,m) scanf("%d%d",&u,&v);
    26     rep(i,1,n) rep(j,1,K) scanf("%d",&t[i][j]);
    27     rep(i,1,K) rep(j,1,K) scanf("%d",&r[i][j]);
    28     rep(i,1,K) lnk[i]=-1;
    29     rep(i,1,n) work(i,i);
    30     rep(i,1,K) if (~lnk[i]) ans[lnk[i]]=i;
    31     rep(i,1,n) printf("%d ",ans[i]);
    32     return 0;
    33 }
    View Code
  • 相关阅读:
    Linux下C程序的反汇编【转】
    数据在内存中的存储方式( Big Endian和Little Endian的区别 )(x86系列则采用little endian方式存储数据)【转】
    linux arm的存储分布那些事之一【转】
    linux arm mmu基础【转】
    linux 进程内存解析【转】
    如何更方便的查看Linux内核代码的更新记录【转】
    设备树解析【转】
    分析内核源码,设备树【转】
     Meltdown论文翻译【转】
    device tree --- #address-cells and #size-cells property【转】
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10806296.html
Copyright © 2020-2023  润新知