noip2008

火柴棍等式

不知道为什么错了的搜索。。。

#include<bits/stdc++.h>
using namespace std;

const int a[]={6,2,5,5,4,5,6,3,7,6};
int ans,n,e[2002];

void dfs(int sum,int x,int val,int bef,int he,int op,int sit)
{
   //cout<<sum<<" "<<x<<" "<<val<<" "<<he<<" "<<op<<endl;
   for(int i=0;i<10;i++)
   	if(a[i]<=sum-x) dfs(sum,x+a[i],val*10+i,bef,he,op,sit);
   if(x-sum==0)  
   {
   	if(op==1) 
   		for(int i=sum+2;i<=n-2;i++) dfs(i,x,0,bef,val,2,sit);
   	if(op==2) {if(bef==val) dfs(n,x,0,bef,he+val,3,1); else dfs(n,x,0,bef,he+val,3,0);}
   	if(op==3) 
   		if(he==val) 
   		{
   			if(sit==1) e[bef]=1;
   			else ans++;
   		}
   }
}		
   					
int main()
{
   scanf("%d",&n); n-=4;
   	
   for(int i=2;i<=n-4;i++) dfs(i,0,0,0,0,1,0);
   for(int i=0;i<=2001;i++) if(e[i]) ans++;
   cout<<ans<<endl;
   return 0;
}

正解(很巧妙,没想到,copy自洛谷第一篇题解)

#include<stdio.h>
int main()
{
        int a[2001]={6},b,c[10]={6,2,5,5,4,5,6,3,7,6},s=0,i,j;
        scanf("%d",&b);
        for(i=1;i<=2000;i++)
        {
                j=i;
                while(j>=1)//求每个数所用的火柴棒
                {
                        a[i]=a[i]+c[j%10];
                        j=j/10;
                }
        }
        for(i=0;i<=1000;i++)
        {
                for(j=0;j<=1000;j++)
                if(a[i]+a[j]+a[i+j]+4==b)s++;//还有加号与等号
        }
        printf("%d",s);
        return 0;
}

双栈排序

好难,想不到;
先考虑一个栈,题解里都只是给出了一个结论:对于i<j<k,存在a[k]<a[i]<a[j],则i,j不能放进一个栈里(题解只证了必要性,我觉得要证充分性才行,但我不会)

然后就是二分图的标准建模了,把所有的i,j不能放进栈里的连一条边,然后染色,为1的放进第一个栈,为2的放进第二个栈,如果不是二分图就是无解;

code

#include<bits/stdc++.h>
using namespace std;
const int N=1010,inf=0x3f3f3f3f;

int read()
{
	int x=0,p=1; char ch=getchar();
	while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
	if(ch=='-') p=-1,ch=getchar();
	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*p;
}

queue<int> Q;
int a[N],f[N],stk1[N],stk2[N],e[N][N],col[N];
int n,top1,top2,now=1;

void bfs(int t)
{
	while(Q.size()) Q.pop();
	Q.push(t); col[t]=1;
	while(Q.size())
	{
		int x=Q.front(); Q.pop();
		for(int i=1;i<=n;i++)
			if(e[x][i])
			{
				if(col[i]==col[x]) { puts("0"); exit(0);}
				if(!col[i]) { col[i]=3-col[x]; Q.push(i); }
			}
	}
}
	
void print1(int x)
{
	while(top1 && a[x]>stk1[top1]) { printf("b "); top1--; }
	stk1[++top1]=a[x];
	printf("a ");
}

void print2(int x)
{
	while(top2 && a[x]>stk2[top1]) { printf("d "); top2--; }
	stk2[++top2]=a[x];
	printf("c ");
}

int main()
{
	n=read();
	f[n+1]=inf;
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=n;i>=1;i--) f[i]=min(a[i],f[i+1]);
	
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)
			if(a[i]<a[j] && f[j+1]<a[i]) e[i][j]=e[j][i]=1;
	
	for(int i=1;i<=n;i++) if(!col[i]) bfs(i);
	
	for(int i=1;i<=n;i++)
	{
        if(col[i]==1)
		{    
            stk1[++top1]=a[i];
            printf("a ");            
        }
        else {
            stk2[++top2]=a[i];
            printf("c ");               
        }
        while((top1 && stk1[top1]==now) || (top2 && stk2[top2]==now))
		{  
            if(top1 && stk1[top1]==now)
			{
                top1--;
                now++;
                printf("b ");
            }
            else
			{
                top2--;
                now++;
                printf("d ");                
            }
        }
	}
	return 0;
}

后面模拟我本来是这样写的,但错了

void print1(int x)
{
	while(top1 && a[x]>stk1[top1]) { printf("b "); top1--; }
	stk1[++top1]=a[x];
	printf("a ");
}

void print2(int x)
{
	while(top2 && a[x]>stk2[top1]) { printf("d "); top2--; }
	stk2[++top2]=a[x];
	printf("c ");
}

for(int i=1;i<=n;i++)
		if(col[i]==1) print1(i);
		else print2(i);
	while(top1) { printf("b "); top1--; }
	while(top2) { printf("d "); top2--; }

posted @ 2019-08-19 20:15  小蒟蒻lzq  阅读(185)  评论(0编辑  收藏  举报