zoukankan      html  css  js  c++  java
  • 11.23

    11.23

    t1 chess——记搜dp

    状态设错了,就靠着(0)骗分了

    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N=155;
    const int P=1e9+7;
    inline int read() {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    int n,m,lim;
    int f[N][N][25][25]; 
    inline void add(int &x,int y){x+=y;if(x>=P) x-=P;}
    inline int work(int a,int b,int c,int d) {
    	if(a==n&&b==m) return 1;
    	if(f[a][b][c][d]!=-1) return f[a][b][c][d];
    	int tmp=0;
    	if(a<n&&c<lim) add(tmp,work(a+1,b,c+1,max(0,d-1)));
    	if(b<m&&d<lim) add(tmp,work(a,b+1,max(0,c-1),d+1));
    	return f[a][b][c][d]=tmp;
    }
    int main() {
    	n=read();m=read();lim=read();
        for(int i=0;i<=n;i++)
           for(int j=0;j<=m;j++)
              for(int x=0;x<=lim;x++)
                 for(int y=0;y<=lim;y++)
                 	f[i][j][x][y]=-1;
    	printf("%d
    ",work(0,0,0,0));
    	return 0;
    }
    

    t2 taxi ——记搜

    20分暴力写挂呜呜呜 ——啊是读题出锅了,一定要严格按照编号大小上车(我以为这个限制只是对于在同一停靠站的)

    ???一套题三道搜索

    我们发现我们并不需要记录编号,我们并不关心出租车里是谁,我们只关心车里的人要到哪里
    去,所以只需要记录要到达的停靠点编号,由于4人满后必须要送一个人到目的地,所以我们只需要记录3个人的目的地即可,这样会出现较多的重复状态,可以用记忆化搜索减少重复状态的搜索。 时间复杂度
    (O(nk^4))

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    const int N=2005;
    inline int read() {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    int n,k,u[N],v[N];
    int f[2005][11][11][11][11]; 
    //当前编号,当前位置,三个目的地位置
    inline int dis(int x){return x>0?x:(-x);}
    inline void Min(int &x,int y){if(x>y)x=y;}
    int dfs(int i,int pos,int a,int b,int c) {
    	if(~f[i][pos][a][b][c]) return f[i][pos][a][b][c];
    	int res=0x3f3f3f3f;
    	// 如果出租车不为空
    	if(a) Min(res,dfs(i,a,0,b,c)+dis(a-pos)+1);
    	if(b) Min(res,dfs(i,b,a,0,c)+dis(b-pos)+1);
    	if(c) Min(res,dfs(i,c,a,b,0)+dis(c-pos)+1);
    	if(i>n) {
    		if(a==0&&b==0&&c==0) return 0;
    		return f[i][pos][a][b][c]=res;
    	}
    	// 如果此时出租车坐满了,先下去一个人
    	if(a && b && c) {
    		Min(res,dfs(i+1,v[i],a,b,c)+dis(u[i]-pos)+dis(u[i]-v[i])+2);
    		Min(res,dfs(i+1,a,v[i],b,c)+dis(u[i]-pos)+dis(u[i]-a)+2);
    		Min(res,dfs(i+1,b,a,v[i],c)+dis(u[i]-pos)+dis(u[i]-b)+2);
    		Min(res,dfs(i+1,c,a,b,v[i])+dis(u[i]-pos)+dis(u[i]-c)+2);
    	}
    	else {
    		if(!a) Min(res,dfs(i+1,u[i],v[i],b,c)+dis(pos-u[i])+1);
    		else if(!b) Min(res,dfs(i+1,u[i],a,v[i],c)+dis(pos-u[i])+1);
    		else Min(res,dfs(i+1,u[i],a,b,v[i])+dis(pos-u[i])+1);
    	}
    	return f[i][pos][a][b][c]=res;
    }
    int main() {
    	memset(f,0xff,sizeof(f));//赋值为-1
    	n=read();k=read();
    	for(int i=1;i<=n;i++) u[i]=read(),v[i]=read();
    		printf("%d
    ",dfs(1,1,0,0,0));;
    	return 0;
    }
    

    t3 stone 折半爆搜

    数据范围显然了,搜出前一半,然后搜后一半。就到这我傻了...我以为要存下来两个数组一个一个对应加再(\%m)找最大值,那这复杂度不又回到 (O(2^35))了???不管了想不透打暴力

    考完被(wkp)一语惊醒,加到超过(m)的后再(\%m)肯定不优了——肯定还不如自己大

    所以只要(*--upperbound(m-1-sum))即可

    还是太傻了

    #include <set>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N=45;
    inline int read() {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    inline void Max(int &x,int y){if(x<y)x=y;}
    int n,m,a[N];
    set<int>s;
    int ans;
    void dfs(int x,int sum) {
    	if(x==n/2+1) {
    		s.insert(sum);
    		return;
    	}
    	dfs(x+1,sum);
    	dfs(x+1,(sum+a[x])%m);
    }
    void dfs2(int x,int sum) {
    	if(x==n+1) {
    		set<int>::iterator it=s.upper_bound(m-sum-1);
    		Max(ans,*(--it)+sum);
    		return;
    	}
    	dfs2(x+1,sum);
    	dfs2(x+1,(sum+a[x])%m);
    }
    int main() {
    	n=read();m=read();
    	bool flag=1;
    	for(int i=1;i<=n;i++) {
    		a[i]=read()%m;		
    		if(a[i]) flag=0;
    	}
    	if(flag) {
    		puts("0");return 0;
    	}
    	s.insert(0);	
    	dfs(1,0);
    	dfs2(n/2+1,0);
    	printf("%d
    ",ans);
    	return 0;
    }
    

  • 相关阅读:
    2016 Multi-University Training Contest 5 ATM Mechine
    2016 Multi-University Training Contest 5 Divide the Sequence
    UVA 10082 WERTYU
    UVA 272 TEX Quotes
    紫书理解
    Codeforces Round #363 (Div. 2) One Bomb
    BestCoder Round #85 hdu5778 abs(素数筛+暴力)
    计算几何模板
    BestCoder Round #85 hdu5777 domino
    BestCoder Round #85 hdu5776 sum
  • 原文地址:https://www.cnblogs.com/ke-xin/p/14024478.html
Copyright © 2011-2022 走看看