バースト肝臓三時間の提供。
Qは、実際に中国聯通、求めて尋ねユニコムブロックが含まれた第2の最大のノードの最初のブロック番号のために必要とされ、これはDFSとともに要求であってもよい。具体的には、我々は最初の図は、セーブセット(\をB [i]は[J ] [0/1/2/3]は\)ポイント$(i、j)は$ 4が壁面を有するかどうかを示し、それぞれの未訪問の時点= 0/1/2 /列挙Kを開始 3 、次いで外方第一のリンクブロックに属する点の数(Q 4が有用である)を記録しながら、展開、リンクブロックは、ノードの数などの情報を含みます。
私たちは、ノードの数と、いくつかユニコムユニコムブロックに属する各ブロックの各点の上に記録されたDFSので、第三及び第四一緒に尋ね尋ねた。私たちは、直接列挙は、あなたが最大ユニコムブロックを取得することができ、壁を断りましたしたがって、我々は、ノードの数が2つのブロックをリンクしMAXNサイズ比較を合計することができる場合にブロックは、異なるユニコムに属しているかどうかを決意限り、壁の両側のノードを列挙します。
第四の問題については、プログラムが出力され、優れたより西に最適な、次善の南、北の壁の東側の壁ので、それでは、列の順序を列挙させ、その後開催された部分を逆に、第三の要求を依頼するのと同じ方法を使用して断りましたユニコムは、壁の後ろに新しいブロックの数は聞いて3番目の質問に等しい。それは直接出力(今回はタイトルの最良の壁の意味に沿ったものでなければならない)である場合。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=55;
int n,m,now,ans1,ans2,ans3;
int visit[N][N],size[N*N];
int a[N][N],b[N][N][4];
inline void dfs(int x,int y){
if(x<1||x>n||y<1||y>m)return;
visit[x][y]=ans1;++now;++size[ans1];
for(int i=0;i<=3;++i){
if(b[x][y][i]==1)continue;
if(i==0&&!visit[x][y-1])dfs(x,y-1);
if(i==1&&!visit[x-1][y])dfs(x-1,y);
if(i==2&&!visit[x][y+1])dfs(x,y+1);
if(i==3&&!visit[x+1][y])dfs(x+1,y);
}
return;
}
int main(){
m=read(),n=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
a[i][j]=read();
for(int k=0;k<=3;++k){
if(a[i][j]&(1<<k))b[i][j][k]=1;
}
}
memset(size,0,sizeof(size));
while(now<n*m){
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(visit[i][j]==0){
++ans1;dfs(i,j);
ans2=max(ans2,size[ans1]);
}
}
printf("%d\n%d\n",ans1,ans2);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
for(int k=0;k<=3;++k){
if(b[i][j][k]){
if(k==0){
if(j-1<1)continue;
if(visit[i][j]==visit[i][j-1])continue;
ans3=max(ans3,size[visit[i][j]]+size[visit[i][j-1]]);
}
if(k==1){
if(i-1<1)continue;
if(visit[i][j]==visit[i-1][j])continue;
ans3=max(ans3,size[visit[i][j]]+size[visit[i-1][j]]);
}
if(k==2){
if(j+1>m)continue;
if(visit[i][j]==visit[i][j+1])continue;
ans3=max(ans3,size[visit[i][j]]+size[visit[i][j+1]]);
}
if(k==3){
if(i+1>n)continue;
if(visit[i][j]==visit[i+1][j])continue;
ans3=max(ans3,size[visit[i][j]]+size[visit[i+1][j]]);
}
}
}
}
}
printf("%d\n",ans3);
for(int j=1;j<=m;++j)
for(int i=n;i>=1;--i){
if(b[i][j][1]&&i-1>=1){
if(visit[i][j]!=visit[i-1][j])
if(size[visit[i][j]]+size[visit[i-1][j]]==ans3){
printf("%d %d N\n",i,j);
return 0;
}
}
if(b[i][j][3]&&i+1<=n){
if(visit[i][j]!=visit[i+1][j])
if(size[visit[i][j]]+size[visit[i+1][j]]==ans3){
printf("%d %d N\n",i+1,j);
return 0;
}
}
if(b[i][j][0]&&j-1>=1){
if(visit[i][j]!=visit[i][j-1])
if(size[visit[i][j]]+size[visit[i][j-1]]==ans3){
printf("%d %d E\n",i,j-1);
return 0;
}
}
if(b[i][j][2]&&j+1<=m){
if(visit[i][j]!=visit[i][j+1])
if(size[visit[i][j]]+size[visit[i][j+1]]==ans3){
printf("%d %d E\n",i,j);
return 0;
}
}
}
return 0;
}
直接列挙すべてのスコア、およびソート順。しかし、そのような分母などの詳細の一部がゼロでない時間を慎重に列挙すること、GCD(分子、分母)= 1、分子がゼロにのみ正当な答えは「0/1」でありますように。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
struct ppx{
double val;int i,j;
}a[40005];
inline bool cmp(const ppx &x,const ppx &y){return x.val<y.val;}
inline int gcd(int a,int b){
if(b==0)return a;
return gcd(b,a%b);
}
int main(){
int n=read(),tot=0;
for(int i=0;i<=n-1;++i){
for(int j=i+1;j<=n;++j){
if(i==0&&j==1){
a[++tot].val=(double)i*1.0/j;
a[tot].i=i;a[tot].j=j;
continue;
}
if(i==1){
a[++tot].val=(double)i*1.0/j;
a[tot].i=i;a[tot].j=j;
continue;
}
if(i!=0){
if(gcd(i,j)==1){
a[++tot].val=(double)i*1.0/j;
a[tot].i=i;a[tot].j=j;
continue;
}
}
}
}
sort(a+1,a+tot+1,cmp);
for(int i=1;i<=tot;++i)
printf("%d/%d\n",a[i].i,a[i].j);
printf("1/1\n");
return 0;
}
そして、最初に私はそれがタイトルのテンプレートの逆マージソートを求めていたと思ったが、タイトルは為替の2数に隣接していなくてもよいです...
貪欲な思考、異なるスイッチング優先順位がサブ二つの位置iを見つけることと、比較次いで、アレイI bの対応する位置に配列bを維持するの昇順で最初の配列、J jは正当な交換(すなわち、のみです次いでjに[J] = B [I]を選択しない場合は[j]は、B [i]と[I] = bの[J])を=。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=1005;
int a[N],b[N];
int main(){
int n=read();
for(int i=1;i<=n;++i)a[i]=read(),b[i]=a[i];
sort(b+1,b+n+1);
int ans=0;
for(int i=1;i<=n;++i){
if(a[i]!=b[i]){
++ans;int bj=0;
for(int j=n;j>=i+1;--j){
if(a[j]==b[i]&&a[i]==b[j]){bj=1;swap(a[i],a[j]);break;}
}
if(bj)continue;
for(int j=n;j>=i+1;--j){
if(a[j]==b[i]){bj=1;swap(a[i],a[j]);break;}
}
}
}
printf("%d\n",ans);
return 0;
}
直接DFSタイムアウト、剪定を考えます。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=50;
int n,m,a[N][N];
int v[N],b[N],visit[N];
inline bool check(){
for(int i=1;i<=n;++i)
if(b[i]<v[i])return false;
return true;
}
inline void dfs(int now,int nowm,int goal){
if(now>goal){
if(check()){
printf("%d ",goal);
for(int i=1;i<=m;++i)
if(visit[i])printf("%d ",i);
printf("\n");
exit(0);
}
return;
}
if(m-nowm+1<goal-now)return;//剪枝1
for(int i=nowm;i<=m;++i){//剪枝2:从上一次选的位置+1开始选
if(!visit[i]){
visit[i]=1;
for(int j=1;j<=n;++j)b[j]+=a[i][j];
dfs(now+1,i+1,goal);
visit[i]=0;
for(int j=1;j<=n;++j)b[j]-=a[i][j];
}
}
}
int main(){
n=read();for(int i=1;i<=n;++i)v[i]=read();
m=read();
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j)
a[i][j]=read();
for(int i=1;i<=m;++i){
for(int j=1;j<=m-i+1;++j){
memset(visit,0,sizeof(visit));
memset(b,0,sizeof(b));
dfs(1,j,i);
}
}
return 0;
}
この質問の難しさは、質問の意味が、私は??? Bがやっているかわからないされている理解することです。
直接小から大に0列挙する\(2 ^ {-1}。1 B + \) 、次いで、及びか否かを判断する前に、D nに上記出力以上との距離の数。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
int n,m,B,D,ans[105];
inline bool pd(int x,int y){
int s=x^y,sum=0;
for(int i=0;(1<<i)<=s;i++)
if((1<<i)&s)sum++;
return sum>=D;
}
inline bool check(int x){
for(int i=1;i<=m;i++)
if(!pd(x,ans[i]))return false;
return true;
}
int main(){
n=read(),B=read(),D=read();
for(int i=0;i<(1<<(B+1))&&m<n;++i)
if(check(i))ans[++m]=i;
for(int i=1;i<=n;++i){
printf("%d ",ans[i]);
if(i%10==0)puts("");
}puts("");
return 0;
}