练习备份3

#include<set>
#include<queue>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<vector>
using namespace std;
const int INF = 0xFFFFFFF; 
const int maxn = 51;
int n,m,k;
struct Node{
    int x,y;
    Node(){ x=y=0;}
    Node(int _x,int _y){ x=_x,y=_y;}
};
set<int>p[26];
Node person[51],post[26];
double d[26];
bool canUse[26];
void test(){
    for(int i=0;i<m;i++)
    if(canUse[i])
    {
        printf("邮局%d的村民有 :",i+1);
        for(set<int>::iterator it=p[i].begin();it!=p[i].end();it++) printf("%d ",*it+1);
        printf("
总距离%lf
",d[i]);
    }
}
double dis(int index1,int index2)
{
    Node house = person[index1];
    Node po = post[index2];
    int x1=house.x,y1=house.y;
    int x2=po.x,y2=po.y;
    double sum = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
    return sqrt(sum);
}
int findMinPost(int index) //找到最近的邮局的编号(可用的邮局) 
{
    Node temp=person[index];//找到这个人的最近可用邮局
    double MIN = INF;
    int u = -1;
    for(int i=0;i<m;i++)
    {
        if(canUse[i])
        {
            if(dis(index,i)<MIN) 
            {
                u=i;
                MIN=dis(index,i);
            }
        }    
    }
    return u; 
}
int main(void)
{
    int x,y;
    cin>>n>>m>>k;
    for(int i=0;i<n;i++)
    {
        cin>>x>>y;
        person[i].x=x,person[i].y=y;
    }
    for(int i=0;i<m;i++)
    {
        cin>>x>>y;
        canUse[i]=true;
        post[i].x=x,post[i].y=y;
    }
    for(int i=0;i<n;i++)
    {
        int pos=findMinPost(i);
        p[pos].insert(i);
    }
    for(int i=0;i<m;i++)
    {
        d[i]=0;
        for(set<int>::iterator it=p[i].begin();it!=p[i].end();it++)
        {
            d[i]+=dis(*it,i);
        }
    }
    //test
    test();
    for(int i=0;i<m-k;i++)//删除m-k个邮局 
    {
        printf("第%d次删除
",i+1);
        int u=-1,MIN=INF;
        for(int j=0;j<m;j++)
        if(canUse[i])
        {
            if(p[j].size()<MIN) 
            {
                u=j,MIN=p[j].size();
            }
            else if(p[j].size()==MIN)
            {
                if(d[j]>d[u])
                {
                    u=j;
                    MIN=p[j].size();
                }
            }
        }
        canUse[u]=false; 
        for(set<int>::iterator it=p[u].begin(); it != p[u].end();it++)
        {
            int pos=findMinPost(*it);
            p[pos].insert(*it);
            d[pos]+=dis(*it,pos);
        }
        test();
        printf("

");
    }
    for(int i=0;i<m;i++)
     if(canUse[i]) printf("%d ",i+1); 
    return 0;    
} 
</pre>AC思路(dfs+剪枝):dfs最重要的就是建立搜索树,这里每个点都有两种状态,如果直接暴力时间肯定很长,所以需要加上剪枝,我们可以将村子的住户还有备用邮局看作是两个集合,就像普利姆的思路一样,总的思路就是更新最短距离数组,我们先将所有的点全部连接在第一个备用邮局,也可以不连第一个,毕竟每个点有两种状态,如果第二个备用邮局到住户的距离足以更新最短距离数组,那就更新之后寻找下一个邮局,如果不足以更新最短距离数组,我们就直接放弃这个点,显然他是没有用的,找到k个邮局之后就判定一下话费,是否更短,如果是,更新序号数组  
[cpp] view plaincopyprint?
#include<iostream>    
#include<stdlib.h>  
#include<math.h>  
using namespace std;  
int n,m,k,j,c[55][2],y[27][2],d[12],f1,f2,f[55]={0};  
float yc[27][55],s=1000000000;  
int dfs(int t,int i,int o[12],float w[55],float sum)  
{  
    if(i<=m+1)  
    {  
        if(t==k)
        {  
             if(sum<s)  
            {  
                s=sum;  
                for(j=0;j<k;j++)  
                    d[j]=o[j];  
            }  
        }  
        else if(i<=m&&t<k)  
        {  
            float ww[55];   
            for(j=1;j<=n;j++)  
            ww[j]=w[j];
            dfs(t,i+1,o,w,sum);
            
            f1=1,f2=0;
            if(!f[i])  
            {  
                o[t]=i;  
                if(t>0)  
                {  
                    f2=1;   
                    for(j=1;j<=n;j++)  
                    {  
                        if(ww[j]>yc[i][j])  
                        {  
                            sum=sum-ww[j]+yc[i][j];   
                            ww[j]=yc[i][j];  
                            f1=0;
                        }  
                    }  
                }  
                else  
                {  
                    for(j=1;j<=n;j++)  
                    {  
                        sum+=yc[i][j];
                        ww[j]=w[j]=yc[i][j];  
                    }  
                }  
                if(f1&&f2)
                {  
                    f[i]=1;
                    dfs(t,i+1,o,w,sum);
                }  
                else  
                dfs(t+1,i+1,o,ww,sum); 
            }  
        }  
    }  
}  
int main()  
{  
    int i,j,o[12];  
    float w[55],ww[55];  
    cin>>n>>m>>k;  
    for(i=1;i<=n;i++)  
    cin>>c[i][0]>>c[i][1];  
    for(i=1;i<=m;i++)  
    {  
        cin>>y[i][0]>>y[i][1];  
        for(j=1;j<=n;j++)  
        yc[i][j]=sqrt((c[j][0]-y[i][0])*(c[j][0]-y[i][0])+(c[j][1]-y[i][1])*(c[j][1]-y[i][1]));  
    }  
    dfs(0,1,o,w,0);  
    for(i=0;i<k;i++)  
    cout<<d[i]<<" ";  
    return 0;  
}  
/*
#include<iostream>  
#include<algorithm>  
using namespace std;  
int main()  
{  
    int a[]={1,2,3,4,5,6};  
    sort(a,a+6);  
    do  
    {  
        for(int i=0;i<6;i++)  
            cout<<a[i];  
        cout<<endl;  
    }while(next_permutation(a,a+6));  
    return 0;  
} 
*/
#include<iostream>  
#include<algorithm>  
using namespace std;  
int main()  
{  
    int a[]={1,2,3,4,5,6};  
    sort(a,a+6);  
    reverse(a,a+6);  
    do  
    {  
        for(int i=0;i<6;i++)  
            cout<<a[i];  
        cout<<endl;  
    }while(prev_permutation(a,a+6));  
    return 0;  
}   
原文地址:https://www.cnblogs.com/zuimeiyujianni/p/8875255.html