HDU--3920[Clear All of Them I] 状态压缩DP或模拟退火

来源:互联网 发布:淘宝上下架规则和流量 编辑:程序博客网 时间:2024/05/19 17:48


PS、正解貌似是状态压缩DP,DP依旧不会、感觉和售货员问题差不多,于是试了下模拟退火居然还真水过去了= =!

 

后然用状态压缩DP也写了一次、、、、、


 

CODE(1):模拟退火

/*模拟退火*//*AC代码:890ms*/#include <iostream>#include <cstdio>#include <memory.h>#include <algorithm>#include <ctime>#include <cmath>#define min(a,b) (a<b?a:b)#define RunN 70#define RanN 70#define INF 1e8using namespace std;struct Node{    int link[25];    double len;};struct Node node[RanN+5];double X[40],Y[40];double ox,oy;double map[40][40];double dis[40];double ans;bool vis[40];int N,cas;void adjust(Node &now,int rn)//rn为调整次数  {      int i,u,v;      while(rn--)      {          u=rand()%(2*N)+1;        v=rand()%(2*N)+1;        if(u==v||now.link[u]==v) continue;        int du=now.link[u];        int dv=now.link[v];        now.link[u]=v;        now.link[v]=u;        now.link[du]=dv;        now.link[dv]=du;    }     double len=0;    memset(vis,false,sizeof(vis));    for(i=1;i<=2*N;i++)    {        if(vis[i]) continue;        v=now.link[i];        len+=map[i][v];        len+=min(dis[i],dis[v]);        vis[i]=vis[v]=true;    }    now.len=len;}  void get_rnode()//产生RANN组初始数列  {      int i,j;      for(i=0;i<RanN;i++)      {          for(j=1;j<=N;j++)        {            node[i].link[j]=j+N;            node[i].link[j+N]=j;        }        adjust(node[i],N-1);//初始调整      }  }  void Run(){    int i,j;    for(i=1;i<=2*N;i++)    {        map[i][i]=0;        for(j=i+1;j<=2*N;j++)        {            map[i][j]=map[j][i]=sqrt((X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j]));        }    }    for(i=1;i<=2*N;i++)        dis[i]=sqrt((X[i]-ox)*(X[i]-ox)+(Y[i]-oy)*(Y[i]-oy));}void Init(){    int i,j;    scanf("%lf%lf",&ox,&oy);    scanf("%d",&N);    for(i=1;i<=2*N;i++)        scanf("%lf%lf",&X[i],&Y[i]);    Run();    get_rnode();}void Print(){    int i;    printf("--------------\n");    for(i=0;i<RanN;i++)        printf("%.2lf\n",node[i].len);    printf("--------------\n");}void Solve(){    int i,j,u,v,t=N-1;    Node temp;    //Print();    while(t--)    {        for(i=0;i<RanN;i++)        {            for(j=0;j<RunN;j++)            {                temp=node[i];                adjust(temp,t);                if(temp.len<node[i].len)                    node[i]=temp;            }        }    }    double ans=INF;    for(i=0;i<RanN;i++)    {        if(ans>node[i].len)            ans=node[i].len;    }    printf("Case #%d: %.2lf\n",cas++,ans);}int main(){    int T;    cas=1;    srand(time(0));    scanf("%d",&T);    while(T--)    {        Init();        Solve();    }    return 0;}


 

 

CODE(2):状态压缩DP

/*状态压缩DP*//*AC代码:531ms*/#include <iostream>#include <cstdio>#include <memory.h>#include <algorithm>#include <queue>#include <cmath>#define MAXN 2000000#define INF 1e8#define min(a,b) (a<b?a:b)#define GOAL ((1<<(2*N))-1)using namespace std;int N,cas;double X[30],Y[30];double map[30][30];double dis[30]; double ox,oy;double dp[MAXN];bool vis[MAXN];int base[30];void get_base(){    int i;    base[0]=1;    for(i=1;i<30;i++)        base[i]=base[i-1]<<1;}void Run(){    int i,j;    for(i=0;i<2*N;i++)    {        map[i][i]=0;        for(j=i+1;j<2*N;j++)        {            map[i][j]=map[j][i]=sqrt((X[i]-X[j])*(X[i]-X[j])+(Y[i]-Y[j])*(Y[i]-Y[j]));        }    }    for(i=0;i<2*N;i++)        dis[i]=sqrt((X[i]-ox)*(X[i]-ox)+(Y[i]-oy)*(Y[i]-oy));    for(i=0;i<MAXN;i++)        dp[i]=INF;    dp[0]=0;}void Init(){    int i;    scanf("%lf%lf",&ox,&oy);    scanf("%d",&N);    for(i=0;i<2*N;i++)        scanf("%lf%lf",&X[i],&Y[i]);    Run();}//类似SPFAqueue<int>Q; double BFS(){    int i,u,pos,state;    double d;memset(vis,false,sizeof(vis));    while(!Q.empty()) Q.pop();    Q.push(0);vis[0]=true;    while(!Q.empty())    {                u=Q.front();Q.pop();vis[u]=false;pos=2*N;        for(i=0;i<2*N;i++)//先找到第一个为零的点,并固定下来        {            if((u&base[i])==0)             {pos=i;break;}        }        for(i=pos+1;i<2*N;i++)//然后O(N)扫描        {            if((u&base[i])==0)             {                d=dp[u]+map[pos][i]+min(dis[i],dis[pos]);                state=((u|base[pos])|base[i]);                if(dp[state]>d)                {                    dp[state]=d;if(!vis[state]){vis[state]=true;Q.push(state);}                }               }                    }    }    return dp[GOAL];}void Print(){    int i;    printf("%d\n",GOAL);    for(i=0;i<2*N;i++)        printf("%.2lf ",dis[i]);    printf("\n");}void Solve(){    //Print();    double ans=BFS();printf("Case #%d: %.2lf\n",cas++,ans);}int main(){    int T;    cas=1;get_base();    scanf("%d",&T);    while(T--)    {        Init();        Solve();    }return 0;}


 


 

原创粉丝点击