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; }