【洛谷P1361】小猫爬山

来源:互联网 发布:mysql已删除的表 编辑:程序博客网 时间:2024/04/19 15:12

【简单题,请神犇移步】
某知dealpool66告诉我可以用这道题练习模拟退火。
然后我一眼看过去不是贪心吗。。

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<iostream>using namespace std;#define N 28int n,w,a[N];int ans = 0;bool vis[N],flag;bool cmp(const int x,const int y){return x>y;}void dfs(int u,int res){    if(!res)return;    for(int i=u;i<=n;i++)if(!vis[i])    {        if(res>=a[i])        {            vis[i]=true;            dfs(i,res-a[i]);        }            }    }int main(){    cin>>n>>w;    for(int i=1;i<=n;i++)        cin>>a[i];    sort(a+1,a+1+n,cmp);    for(int i=1;i<=n;i++)    {        if(!vis[i])        {            ++ans;vis[i]=true;            dfs(i+1,w-a[i]);            }            }    cout<<ans;    return 0;}

然后就24分了orz。
诶,我感觉贪心思路是对的。。只是直接写要错。。
因为如果刚好能凑满的话直接贪就错了。

啊,于是乎,我开始感觉难实现,然后想了想,发现dfs返回个bool就可以了。
然后。。
代码如下:

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<iostream>using namespace std;#define N 28int n,w,a[N];int ans = 0;bool vis[N];bool cmp(const int x,const int y){return x>y;}bool dfs(int u,int res){    if(!res)return true;    bool flag = false;    for(int i=u;i<=n;i++)if(!vis[i])    {        if(res>=a[i])        {            vis[i]=true;            flag=dfs(i+1,res-a[i]);            if(flag)break;            vis[i]=false;        }           }    if(flag)return true;    for(int i=u;i<=n;i++)    {        if(a[i]<=res)           {            vis[i]=true;            dfs(i+1,res-a[i]);            break;        }    }    return false;}int main(){    cin>>n>>w;    for(int i=1;i<=n;i++)        cin>>a[i];    sort(a+1,a+1+n,cmp);    for(int i=1;i<=n;i++)    {        if(!vis[i])        {            ++ans;vis[i]=true;            dfs(i+1,w-a[i]);            }           }    cout<<ans;    return 0;}

和开始的代码的区别是,判断后面有没有刚好组成w的方案,如果有肯定这种最优,否则,我们就尽量先消除大的。
然后 75分。

数据生成器:

#!usr/bin/env python#-*- coding:utf-8 -*-import randomimport sysfp = open("in.in","w")sys.stdout = fpn =  random.randint(1,18)m =  random.randint(1,10000000)#print >>fp,n#print >>fp,mprint nprint mfor i in range(1,n+1):    #print >>fp,random.randint(1,m)    print random.randint(1,m)


然后QWQ我知道我错了。
但是好像很不容易卡。。
对拍了半天。。

模拟退火

#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<stack>#include<iostream>#include<ctime>using namespace std;int n,w,rpath[1000][20],ans[1000],a[20];void adjust(int *p,int rn){    while(rn--)    {        int x=rand()%n+1;        int y=rand()%n+1;        swap(p[x],p[y]);    }}void get_rpath(){    for(int i=0;i<1000;i++)    {        ans[i]=1e9;        for(int j=1;j<=n;j++)rpath[i][j]=j;        adjust(rpath[i],n-1);    }}int get_val(int *p){    int ret=0,sum=0;    for(int i=1;i<=n;i++)    {        sum+=a[p[i]];        if(sum>w){ret++;sum=a[p[i]];}    }    if(sum)ret++;    return ret;}int main(){    freopen("koneko.in","r",stdin);freopen("koneko.out","w",stdout);    srand(time(NULL));    scanf("%d%d",&n,&w);    for(int i=1;i<=n;i++)scanf("%d",&a[i]);    get_rpath();    int t=n,p[20];    while(t--)    {        for(int i=0;i<1000;i++)        {            for(int j=0;j<50;j++)            {                memcpy(p,rpath[i],sizeof(p));                adjust(p,t);                int tmp=get_val(p);                if(tmp<ans[i])                {                    ans[i]=tmp;                    memcpy(rpath[i],p,sizeof(rpath[i]));                }            }        }    }    int res=ans[0];    for(int i=1;i<1000;i++)res=min(res,ans[i]);    cout<<res<<endl;    return 0;}

正解迭代加深

#include<iostream>#include<cstdio>using namespace std;const int size = 24;int w[size];int z[size];int n,k;bool flag;void dfs(int s,int u){    if(flag)        return ;    if(u > n)    {        flag = 1;        return ;    }    int mx = min(s,u);    for(int i = 1 ; i <= mx ; i ++)    {        if(z[i] + w[u] > k)            continue;        z[i] += w[u];        dfs(s,u+1);        z[i] -= w[u];    }}int main(){    scanf("%d%d",&n,&k);    for(int i = 1 ; i <= n ; i ++)        scanf("%d",&w[i]);    for(int i = 1 ; i <= n ; i ++)    {        dfs(i,1);        if(flag)        {            printf("%d\n",i);            break;        }    }    return 0;}
1 0
原创粉丝点击