sgu 126 Boxes

题意:较大的容量减较小的容量,较小的容量翻倍。问操作几回其中一个空。

开始用set判重,重复就不可行。不过状态最多有2e18种。不仅爆内存,还超时。然后找规律。发现只有比例为1:1,1:3,1:7,3:5,1:15,3:13,5:11,7:9......这样才行。也就是化简以后相加是2^k。

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <cassert>
#include <list>
#define mkp make_pair 
using namespace std;
const double EPS=1e-8;
const int SZ=1e2+10,INF=0x7FFFFFFF;
const long long mod=19999997;
typedef long long lon;

int gcd(int x,int y)
{
    if(x==0)return y;
    if(y==0)return x;
    if(x<y)swap(x,y);
    int res=0;
    for(;;)
    {
        int rem=x%y;
        if(rem==0)return y;
        x=y;
        y=rem;
    }
}

int cnt(int x)
{
    int res=0;
    for(;x;x-=x&-x,++res);
    return res;
}

int chk(int x)
{
    int num=cnt(x);
    if(num!=1)return -1;
    else
    {
        for(int i=0;i<32;++i)
        {
            if((1<<i)&x)return i;
        }
    }
}

int main()
{
    std::ios::sync_with_stdio(0);
    //freopen("d:\\1.txt","r",stdin);
    int casenum;
    //cin>>casenum;
    //scanf("%d",&casenum);
    //for(int time=1;time<=casenum;++time)
    //for(int time=1;cin>>n;++time)
    {
        int n,m;
        cin>>n>>m;
        int d=gcd(n,m);
        //cout<<d<<endl;
        n/=d,m/=d; 
        if(n==0||m==0)cout<<0<<endl;
        else
        {
            cout<<chk(n+m)<<endl;
        }
    }
    return 0;
}

超内存的:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <cassert>
#include <list>
using namespace std;
const double EPS=1e-8;
const int SZ=1e2+10,INF=0x7FFFFFFF;
const long long mod=19999997;
typedef long long lon;
int n,sum[9],arr[9];

bool chk(int x,int t)
{
    int res=0;
    if(x/n&&arr[x]<arr[x-n])++res;
    if(x%n&&arr[x]<arr[x-1])++res;
    if(x/n!=n-1)
    {
        if(t)
        {
            if(arr[x]<arr[x+n])++res;
        }
        else ++res;
    }
    if(x%n!=n-1)
    {
        if(t)
        {
            if(arr[x]<arr[x+1])++res;
        }
        else ++res;
    }
    return t?res==sum[x]:res>=sum[x];
}

bool dfs(int x)
{
    //cout<<x<<endl;
    if(x==n*n)
    {
//        for(int i=0;i<n*n;++i)
//        {
//            cout<<arr[i]<<" ";
//        }cout<<endl;
        return 1;
    }
    for(int i=1;i<10;++i)
    {
        arr[x]=i;
        if(x%n&&chk(x-1,0||((x-1)/n==n-1))==0)continue;
        if(x/n&&chk(x-n,1)==0)continue;
        if(x==n*n-1&&chk(x,1)==0)continue;
        //cout<<x<<" "<<i<<endl;
        if(dfs(x+1))return 1;
        //else cout<<x<<" "<<i<<" fail"<<endl;
    }
    arr[x]=0;
    return 0;
}

int main()
{
    std::ios::sync_with_stdio(0);
    //freopen("d:\\1.txt","r",stdin);
    int casenum;
    //cin>>casenum;
    //scanf("%d",&casenum);
    //for(int time=1;time<=casenum;++time)
    //for(int time=1;cin>>n;++time)
    {
        cin>>n;
        for(int i=0;i<n*n;++i)
        {
            cin>>sum[i];
        }
        if(n==1)
        {
            if(sum[0]==0)cout<<1<<endl;
            else cout<<"NO SOLUTION"<<endl;
        }
        else if(dfs(0))
        {
            for(int i=0;i<n*n;++i)
            {
                if(i%n)cout<<" ";
                cout<<arr[i];
                if(i%n==n-1)cout<<endl;
            }
        }
        else
        {
            cout<<"NO SOLUTION"<<endl;
        }
    }
    return 0;
}

超时的:

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <cassert>
#include <list>
#define mkp make_pair 
using namespace std;
const double EPS=1e-8;
const int SZ=1e2+10,INF=0x7FFFFFFF;
const long long mod=19999997;
typedef long long lon;

int work(int x,int y,int x1,int y1,int s)
{
    if(x<y)swap(x,y);
    if(x1<y1)swap(x1,y1);
    //cout<<x<<" "<<y<<" "<<x1<<" "<<y1<<endl;
    if(s!=1&&x==x1&&y==y1)return -1;
    x-=y;
    y*=2;
    x1-=y1;
    y1*=2;
    if(x<y)swap(x,y);
    if(x1<y1)swap(x1,y1);
    //if(s!=1&&x==x1&&y==y1)return -1;
    x1-=y1;
    y1*=2;
    if(x==0||y==0)return s;
    return work(x,y,x1,y1,s+1);
}

int main()
{
    std::ios::sync_with_stdio(0);
    //freopen("d:\\1.txt","r",stdin);
    int casenum;
    //cin>>casenum;
    //scanf("%d",&casenum);
    //for(int time=1;time<=casenum;++time)
    //for(int time=1;cin>>n;++time)
    {
        int n,m;
        cin>>n>>m;
        if(n==0||m==0)cout<<0<<endl;
        else if((n&1)^(m&1))cout<<-1<<endl;
        else cout<<work(n,m,n,m,1)<<endl;
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/gaudar/p/9764809.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值