zoukankan      html  css  js  c++  java
  • ZROI week1

    \[ZROI day1 \]

    $$Grid$$

    • 题目描述
      给定一个矩阵,小写字母,求一条路径使得从\((1,1) -> (n,m)\),字典序最小,并且每次只能向右或者向下。

    • 题解

    先考虑如果没有重复字母,可以再\(dfs\)的过程中不断贪心得到路径。

    如果有重复的话,考虑枚举每条对角线,求出到这条对角线的最小字典序路径和所有可能的结束位置。

    复杂度\(O(n \times m)\)

    还有一种就是考虑预处理出每一步最接近答案的最远点,进行bfs即可。

    ps:忘记\(unique\),考试的时候T1调了一个半小时多。。。

    $$water$$

    • 题目描述

    • 题解
      裸状压dp题。

    ps:这题打挂了就20分

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 30;
    const int INF = (1 << 30) - 1;
    int c[MAXN][MAXN];
    #define rep(i,_,__)for(int i = _;i <= __; ++i)
    #define down(i,_,__) for(int i = _;i >= __; --i)
    const int U = 1 << 21;
    
    
    int f[U];
    int Count(int state) {
    	bitset <100> bit;
    	bit = state;
    	return bit.count();
    }
    
    int n;
    int k;
    #define all (1 << n)
    int ans = INF;
    int main () {
    	cin >> n >> k;
    	rep(i,0,n - 1) {
    		rep(j,0,n - 1) {
    			cin >> c[i][j];
    		}
    	}
    	for(int i = 0;i <= all; ++i) f[i] = INF;
    	f[all - 1] = 0;
    	down(state,all - 1,0) {
    		//cout<<Count(state)<<endl;
    		rep(i,0,n - 1) {
    			if(state & (1 << i)) {
    				rep(j,0,n - 1) {
    					if(i == j) continue;
    					f[(state - (1 << i)) | (1 << j)] = min(f[(state - (1 << i)) | (1 << j)],f[state] + c[i][j]);
    				}
    			}
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

    $$pal$$

    • 题目描述
      给定一个序列,每次可以合并相邻的数字,合并之后是一个新数等于原数之和,求最少合并次数使得变成一个回文序列。

    • 题解
      指针扫描即可。

    证明:
    给定序列:1 5 3 2 1
    考虑分治这个过程,第一个和最后一个相等,那么这个东西就永远不能动,否则会增加次数,如果相等把指针l ++,r --,如果不一样找到小的往前合并,直到相等,类似解子问题的思路。

    ps:一眼+5min证明

    $$LIS$$

    • 题目描述
      按照一定规则构造序列,求构造出的所有序列中LIS长度和数目。

    • ps:先来ps一下,想出来了没时间写,中途去干了某些事情QAQ

    • 题解
      长度好说,贪心构造就行。
      怎么算方案数?
      经典计数问题,设\(f_i\)表示以\(i\)结尾的LIS长度,\(g_i\)表示\(f_i\)的方案数
      略写转移即可,虽然比较难写。

    \[作业 \]

    $$T1 : poj 2411$$

    记录放的状况转移即可。

    #include <cstdio>
    using namespace std;
    #define ll long long
    const int MAXN = 12;
    ll f[MAXN][1 << MAXN];
    bool state[1 << MAXN];
    #define U 1 << m
    int n,m;
    int main () {
    	while(~scanf("%d %d",&n,&m)) {
    		if(!n and !m) return 0;
    		for(int i = 0;i < U; ++i) {
    			bool odd = 0;
    			bool stp = 0;
    			for(int j = 0;j < m; ++j) {
    				if(i >> j & 1) {
    					odd |= stp;
    					stp = 0;
    				}
    				else stp ^= 1;
    			}
    			state[i] = odd | stp ? 0 : 1;
    		}
    		f[0][0] = 1;
    		for(int i = 1;i <= n; ++i) {
    			for(int j = 0;j < U; ++j) {
    				f[i][j] = 0;
    				for(int k = 0;k < U; ++k) {
    					if((j & k) == 0 and state[j | k]) {
    						f[i][j] += f[i - 1][k];
    					}
    				}
    			}
    		}
    		printf("%lld\n",f[n][0]);
    	}
    	return 0;
    }
    

    $$T2 : hdu 6006$$

    枚举每个工程师的情况,做背包即可。

    调了半天...

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    const int MAXN = 20;
    #define ll long long
    #define C continue
    ll f[MAXN][1 << 11];
    vector<int>v[MAXN],a[MAXN],b[MAXN];
    
    int vis[300];
    void Clear() {
    	memset(f,0,sizeof f);
    	memset(vis,0,sizeof vis);
    	for(int i = 0;i < 20; ++i) {
    		v[i].clear();
    		a[i].clear();
    		b[i].clear();
    	}
    }
    #define pb(x) push_back(x)
    int n,T,m;
    int read () {
    	int q=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')f=-1;ch=getchar();
    	}
    	while(isdigit(ch)) {
    		q=q*10+ch-'0';ch=getchar();
    	}
    	return q*f;
    }
    int cas;
    int main () {
    	T = read();
    	while(T--) {
    		Clear();
    		n = read(),m = read();
    		for(int i = 1;i <= n; ++i) {
    			int num = read();
    			for(int j = 1;j <= num; ++j) {
    				a[i].pb(read());
    			}
    		}
    		for(int i = 1;i <= m; ++i) {
    			int num = read();
    			for(int j = 1;j <= num; ++j) {
    				b[i].pb(read());
    			}
    		}
    		for(int i = 1;i <= n; ++i) {
    			for(int j = 0;j < (1 << m); ++j) {
    				memset(vis,0,sizeof vis);
    				int cnt = 0;
    				for(int k = 0;k < m; ++k) {
    					if(j & (1 << k)) {
    						cnt ++;
    						for(int l = 0;l < b[k + 1].size(); ++l) {
    							vis[b[k + 1][l]] ++;
    						}
    					}
    				}
    				if(cnt > 3) C;
    				bool tag = 1;
    				for(int k = 0;k < a[i].size(); ++k) {
    					if(vis[a[i][k]] == 0) {
    						tag = 0;
    					}
    				}
    				if(tag == 1) v[i].pb(j);
    			}
    		}
    		for(int state = 0;state < (1 << m); ++state) {
    			for(int j = 0;j < v[1].size(); ++j) {
    				if((state | v[1][j]) == state) {
    					f[1][state] = 1;
    				}
    			}
    		}
    		for(int i = 2;i <= n; ++i) {
    			for(int state = 0 ;state < (1 << m); ++ state) {
    				for(int j = 0;j < v[i].size(); ++j) {
    					if((state | v[i][j]) == state) {
    						f[i][state] = max(f[i][state],f[i - 1][state - v[i][j]] + 1);
    					}
    				}
    				f[i][state] = max(f[i][state],f[i - 1][state]);
    			}
    		}
    		printf("Case #%d: %lld\n",++cas, f[n][(1 << m) - 1]);
    	}
    	return 0;
    }
    

    $$T3 : hdu 4640$$

    考虑把每个人移动的状态压成二进制,dp即可。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int MAXN = 21;
    const int U = (1 << 18);
    const int INF = 0x3f3f3f3f;
    int T;
    int x,y,z;
    typedef pair<int,int> P;
    int a[MAXN][MAXN];
    int sum;
    int n,m;
    int ans;
    int Q;
    int f[U][MAXN];
    int g[4][U];
    int vis[U][MAXN];
    queue<P>q;
    int cas;
    #define mk(x,y) make_pair(x,y)
    #define fir first
    #define sec second
    void bfs() {
    	q.push(mk(0,0));
    	memset(vis,0,sizeof vis);
    	for(int i = 0;i < (1 << n); ++i) {
    		for(int j = 0;j < n; ++j) {
    			f[i][j] = INF;
    		}
    	}
    	f[0][0] = 0;
    	while(!q.empty()) {
    		P now = q.front();
    		q.pop();
    		int start = now.fir;
    		int end = now.sec;
    		vis[start][end] = 0;
    		for(int i = 0;i < n; ++i) {
    			if(a[end][i] < INF && f[start | (1 << i)][i] > f[start][end] + a[end][i]) {
    				f[start | (1 << i)][i] =f[start][end] + a[end][i];
    				if(vis[start | (1 << i)][i] == 0) {
    					vis[start | (1 << i)][i] = 1;
    					q.push(mk(start | (1 << i),i));
    				}
    			}
    		}
    	}
    }
    
    int main () {
    	cin >> T;
    	while(T--) {
    		cin >> n >> m;
    		for(int i = 0;i <= n; ++i) {
    			for(int j = 0;j <= n; ++j) {
    				a[i][j] = INF;
    				if(i == j) a[i][j] = 0;
    			}
    		}
    		for(int i = 1;i <= m; ++i) {
    			cin >> x >> y >> z;
    			-- x;
    			-- y;
    			a[x][y] = a[y][x] =min(a[x][y],z);
    		}
    		sum = 0;
    		cin >> Q;
    		while(Q--) {
    			int state;
    			cin >> state;
    			sum |= (1 << (state - 1));
    		}
    		bfs();
    		printf("Case %d: ",++cas);
    		for(int i = 1;i <= 3; ++i) {
    			for(int j = 0;j < (1 << n); ++j) {
    				g[i][j] = INF;
    			}
    		}
    		for(int i = 0;i < (1 << n); ++i) {
    			for(int j = 0;j <n; ++j) {
    				g[1][i] = min(g[1][i],f[i][j]);
    			}
    		}
    		for(int i = 2;i <= 3; ++i) {
    			for(int j = 0;j < (1 << n); ++j) {
    				for(int k = j; k ;k = (k - 1) & j) {
    					g[i][j] = min(g[i][j],max(g[1][k],g[i - 1][j ^ k]));
    				}
    			}
    		}
    		ans = INF;
    		for(int i = 1;i <= 3; ++i) {
    			for(int j = 0;j < (1 << n); ++j) {
    				if((sum & j) == sum) {
    					ans = min(ans,g[i][j]);
    				}
    			}
    		}
    		if(ans == INF) {
    			puts("-1");
    		}
    		else cout<<ans<<endl;
    	}
    	return 0;
    }
    

    $$T4 : hdu 4462$$

    枚举每个合法状态,暴力即可。

    ps:hdu居然不认and操作

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <bitset>
    #define C continue
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int MAXN = 51;
    const int MAXM = 11;
    bitset<3000>bit[MAXM],state;
    struct position {
    	int x;
    	int y;
    }p[MAXN << 1];
    bool find(int x,int y,int z) {
    	return x + y <= z;
    }
    int n,k;
    int ans;
    int Range[MAXN * MAXN];
    int vis[MAXN][MAXN];
    int x,y;
    int main () {
    	while(cin >> n && n) {
    		cin >> k;
    		memset(vis,0,sizeof vis);
    		for(int i = 1;i <= k; ++i) {
    			cin >> x >> y;
    			p[i].x = x;
    			p[i].y = y;
    			vis[p[i].x][p[i].y] = 1;
    		}
    		for(int i = 1;i <= k; ++i) {
    			cin >> Range[i];
    		}
    		for(int i = 1;i <= k; ++i) {
    			bit[i].reset();
    			for(int j = 1;j <= n; ++j) {
    				for(int k = 1;k <= n; ++k) {
    					if(vis[j][k]) {
    						C;
    					}
    					if(find(abs(j - p[i].x),abs(k - p[i].y),Range[i])) {
    						bit[i].set((j - 1) * n + k - 1);
    					}
    				}
    			}
    		}
    		ans = INF;
    		for(int i = 0;i < (1 << k); ++i) {
    			int cnt = 0;
    			state.reset();
    			for(int j = 1;j <= k; ++j) {
    				if(i & (1 << (j - 1))) {
    					cnt ++;
    					state |= bit[j];
    				}
    			}
    			if(state.count() == n * n - k) {
    				ans = min(ans,cnt);
    			}
    		}
    		if(ans == INF) {
    			cout<<-1<<endl;
    		}
    		else cout<<ans<<endl;
    	}
    }
    

    $$T5 : hdu 3017$$

    考虑是\(^{30}\),我们用双向搜索,每次让两个方向的搜索选一个状态,最后拼起来判断即可。
    (基本套路)

    finished

  • 相关阅读:
    Windows Azure Web Site (19) Azure Web App链接到VSTS
    Windows Azure Virtual Machine (35) Azure VM通过Linked DB,执行SQL Job
    Azure PowerShell (16) 并行开关机Azure ARM VM
    Windows Azure Virtual Network (12) 虚拟网络之间点对点连接VNet Peering
    Azure ARM (21) Azure订阅的两种管理模式
    Windows Azure Platform Introduction (14) 申请海外的Windows Azure账户
    Azure ARM (20) 将非托管磁盘虚拟机(Unmanage Disk),迁移成托管磁盘虚拟机(Manage Disk)
    Azure ARM (19) 将传统的ASM VM迁移到ARM VM (2)
    Azure ARM (18) 将传统的ASM VM迁移到ARM VM (1)
    Azure Automation (6) 执行Azure SQL Job
  • 原文地址:https://www.cnblogs.com/akoasm/p/10126491.html
Copyright © 2011-2022 走看看