2013 Aizu Regional Contest(UValive 6661,6662,6663,6664,6665,6669)
2015-11-04 00:13
561 查看
A - Equal Sum Sets
题意:
输入三个数 n, k, s .求有多少种集合元素个数为k,元素最大值为n,元素之和为s,集合中元素均不相同.
思路:
暴力由于 n≤20 ,那么只有 220=106 种集合,那么枚举集合判断是否符合条件即可,复杂度为 O(2n∗k),但由于有100组样例。。所以只能很勉强地过,n 再大一点就得跪。
并不推荐这种做法。。
DP
dp[i][j][k]表示 n = i , k = j , s = k 的集合数,dp[i][j][k]可以由两种状态转移得到,一种是集合中有元素 i 的,一种是没有的。
即 dp[i][j][k]=dp[i−1][j][k]+dp[i−1][j−1][k−i]
代码1(暴力):
#include<bits/stdc++.h> using namespace std; int main() { int n , k , s ; while ( cin >> n >> k >> s ) { if ( !n && !k && !s ) break ; int total = ( 1 << n ) ; int ans = 0 ; for ( int i = 0 ; i < total ; i++ ) { int tmp = i , sum = 0 ; int a = 1 , cnt = 0 ; while ( tmp ) { if ( tmp & 1 ) { sum += a ; cnt++ ; if ( sum > s || cnt > k ) break ; } a++ ; tmp >>= 1 ; } if ( sum == s && cnt == k ) ans ++ ; } cout << ans << endl ; } return 0; }
代码2(DP):
#include<bits/stdc++.h> using namespace std; int n , k , s ; int dp[22][12][200] ; void init() { dp[0][0][0] = 1 ; for ( int i = 1 ; i <= 20 ; i++ ) for ( int j = 0 ; j <= 10 ; j++ ) for ( int k = 0 ; k <= 160 ; k++ ) { dp[i][j][k] = dp[i-1][j][k] ; if ( j && k >= i ) dp[i][j][k] += dp[i-1][j-1][k-i] ; } } int main() { init() ; while ( ~scanf( "%d%d%d" ,&n ,&k ,&s ) ) { if ( !n && !k && !s ) break ; printf( "%d\n" , dp [k][s] ) ; } return 0; }
B - The Last Ant
题意:
输入两个数 n , l .n 代表蚂蚁的数量,l 代表木板的长度,接下来输入 n 只蚂蚁所在的位置与行动的方向。
若两只蚂蚁在相邻的两格之间相遇,则掉头而行;若相遇位置在一格中心,则继续沿原方向前进。
已知蚂蚁速度为 1 格/s,求所有蚂蚁都掉下木板所需的时间,并求出最后一个离开木板的蚂蚁编号。
思路:
模拟,模拟,模拟。。代码:
#include<bits/stdc++.h> using namespace std; struct Ant{ int id, pos, leave; char dir[2] ; bool operator < ( const Ant &a )const { return pos < a.pos ; } }; Ant a[25] ; int n , l ; void turn( int i , int j ) { if ( a[i].dir[0] == 'L' ) a[i].dir[0] = 'R' ; else a[i].dir[0] = 'L' ; if ( a[j].dir[0] == 'L' ) a[j].dir[0] = 'R' ; else a[j].dir[0] = 'L' ; } void work() { int time = 0 ; int out = 0 ; Ant last[2] ; while ( 1 ) { time ++ ; for ( int i = 0 ; i < n ; i++ ) { if ( a[i].pos <= 0 || a[i].pos >= l ) continue ; if ( a[i].dir[0] == 'R' ) a[i].pos++ ; else a[i].pos-- ; if ( a[i].pos == 0 || a[i].pos == l ) { out++ ; a[i].leave = time ; last[out&1] = a[i] ; } } sort( a , a + n ) ; for ( int i = 0 ; i < n - 1 ; i++ ) { if ( a[i].pos == a[i+1].pos ) turn( i , i+1 ) ; } if ( out >= n ) break ; } int ans = last[out&1].id; if ( last[1].leave == last[0].leave ) { if ( last[0].dir[0] == 'L' ) ans = last[0].id ; else ans = last[1].id ; } cout << time << ' ' << ans << endl ; } int main() { //freopen("my.in","r",stdin); //freopen("my.out","w",stdout); while ( scanf( "%d%d" ,&n ,&l ) , n || l ) { for ( int i = 0 ; i < n ; i++ ) { scanf( "%s%d" ,a[i].dir ,&a[i].pos ) ; a[i].id = i + 1 ; } sort( a , a + n ) ; work() ; } return 0; }
C - Count the Regions
题意:
给 n 个矩形的坐标,计算整个平面被矩形分成了几个区域。思路:
先离散化,然后把所有矩形边标记为1,然后枚举每一个图内的点,若标记为0则dfs染色,遇到边界停止,并且将答案+1.代码:
//2015/11/1 13:55:53 //#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<functional> #include<string> #include<map> #include<set> #include<vector> #include<queue> #include<stack> #include<bitset> #include<ctime> using namespace std; #define clr( x , y ) memset(x,y,sizeof(x)) #define cls( x ) memset(x,0,sizeof(x)) #define pr( x ) cout << #x << " = " << x << endl #define pri( x ) cout << #x << " = " << x << " " #define test( t ) int t ; cin >> t ; int kase = 1 ; while( t-- ) #define out( kase ) printf( "Case %d: " , kase++ ) #define sqr( x ) ( x * x ) #define mp make_pair #define pii pair<int,int> #define fi first #define se second #define pb push_back typedef long long lint; const double eps = 1e-8 ; const int inf = 0x3f3f3f3f ; const long long INF = 0x3f3f3f3f3f3f3f3fLL ; struct Rec{ int l , r , t , b ; void input() { scanf( "%d%d%d%d" ,&l ,&t ,&r ,&b ) ; } }rec[60] ; const int L = 1e6 + 10 ; int x[120],y[120] ; int xx[L] , yy[L] ; int G[240][240] ; int n , ans , kx , ky , lenx , leny ; const int dir[4][2] = { 1, 0, -1, 0, 0, 1, 0, -1 } ; void discrete() { sort( x , x + kx ) ; sort( y , y + ky ) ; lenx = unique( x , x + kx ) - x ; leny = unique( y , y + ky ) - y ; for ( int i = 0 ; i < lenx ; i++ ) xx[x[i]] = 2 * i ; for ( int i = 0 ; i < leny ; i++ ) yy[y[i]] = 2 * i ; for ( int i = 0 ; i < n ; i++ ) { int x1 = xx[rec[i].l] ; int x2 = xx[rec[i].r] ; int y1 = yy[rec[i].t] ; int y2 = yy[rec[i].b] ; for ( int j = x1 ; j <= x2 ; j++ ) G[j][y1] = G[j][y2] = 1 ; for ( int j = y2 ; j <= y1 ; j++ ) G[x1][j] = G[x2][j] = 1 ; } } bool check( int i , int j ) { bool ok = ( i >= 1 && j >= 1 && i <= 2 * lenx - 2 && j <= 2 * leny - 2 ) ; return ok ; } void dfs( int i , int j ) { G[i][j] = 1 ; for ( int k = 0 ; k < 4 ; k++ ) { int tmpi = i + dir[k][0] ; int tmpj = j + dir[k][1] ; if ( check( tmpi , tmpj ) && !G[tmpi][tmpj] ) dfs( tmpi , tmpj ) ; } } void find() { ans = 0 ; for ( int i = 0 ; i < ( lenx << 1 ) ; i++ ) { if ( !G[i][0] ) dfs( i , 0 ) ; int tmp = ( leny << 1 ) - 1 ; if ( !G[i][tmp] ) dfs( i , tmp ) ; } for ( int i = 0 ; i < ( leny << 1 ) ; i++ ) { if ( !G[0][i] ) dfs( 0 , i ) ; int tmp = ( lenx << 1 ) - 1 ; if ( !G[tmp][i] ) dfs( tmp , i ) ; } for ( int i = 0 ; i < ( lenx << 1 ) ; i++ ) { for ( int j = 0 ; j < ( leny << 1 ) ; j++ ) { if ( !G[i][j] ) ans++ , dfs( i , j ) ; } } } int main() { //freopen("my.in","r",stdin); //freopen("my.out","w",stdout); while ( cin >> n && n ) { kx = 0 , ky = 0 ; cls( G ) ; for ( int i = 0 ; i < n ; i++ ) { rec[i].input() ; x[kx++] = rec[i].l ; x[kx++] = rec[i].r ; y[ky++] = rec[i].t ; y[ky++] = rec[i].b ; } discrete() ; find() ; cout << ans + 1 << endl ; } return 0; }
D - Clock Hands
题意:
有一个时钟,时针每 H 小时走一圈。现在给你一个时刻,求该时刻之后最近的时刻 t ,在时刻 t ,秒针与分针的夹角等于秒针与时针的夹角。
时刻 t 的秒数用分数表示。
思路:
先吐槽一下,,时钟的题目一般都是在纸上写啊写,推出个公式,然后照着公式A过去就行了,结果这题用了半小时推公式,写代码用了两小时。。还是 too simple 啊。设时钟一周的角度为 1,输入时刻为 h : m : s。
秒针转动角度:angs=s60分针转动角度:angm=m60+s3600时针转动角度:angh=hH+m60H+s3600H
设经过 t 秒后,秒针与分针的夹角等于秒针与时针的夹角,即
2∗angs′=angm′+angh′
还有一种情况是分针在0右边,时针在0左边,起初秒针在0
左边,过了几秒后秒针过0,此时,相当于秒针角度减少了一周,所以要在原公式里补上圈数k(k是整数):
设 angs′=angs+angtangm−angs′=angs′+1−angh2∗angs′+1=angm+angh即 2∗(angt+angs)+k=angm+angh
至于分数的处理可以用分数类来做,或者把上式代入来计算gcd:
(119H−1)(s+t)=60(H+1)m+3600h−3600Hk
代码:
#include<bits/stdc++.h> using namespace std; int gcd( int a , int b ) { return b? gcd( b ,a % b ) : a ; } int main() { //freopen("my.in","r",stdin); //freopen("my.out","w",stdout); int H , h , m , s ; while ( cin >> H >> h >> m >> s ) { if ( !H && !m && !h && !s ) break ; int tmp = 119*H - 1 ; //(119H-1)(s+t) = 60(1+H)m + 3600h - 3600Hk int t = 60*(1+H)*m + 3600*h - 3600*H - tmp*s ; while ( t < 0 ) t += 3600*H ; int sec = 60 * s * tmp + 60 * t ; int min = 60 * m * tmp + sec / 60 ; int hour ; if ( sec == min ) t += 3600*H ; sec = s * tmp + t ; min = m + sec / ( tmp * 60 ) ; hour = h + min / 60 ; min %= 60 ; hour %= H ; sec %= tmp * 60 ; int d = gcd( sec , tmp ) ; printf( "%d %d %d %d\n" ,hour ,min ,sec/d ,tmp/d ) ; } return 0; }
E - Dragon’s Cruller
思路:
题意略去。。这题想通了其实挺简单的,康拓展开+优先队列+bfs。
把九宫格转换成一行,那么一个状态就是一种排列,用康拓展开将排列映射到一个数字,然后搜索状态直到符合所求状态,用优先队列维护花费。
代码:
/* Creat Time:2015/11/2 21:27:15 */ //#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<functional> #include<string> #include<map> #include<set> #include<vector> #include<queue> #include<stack> #include<bitset> #include<ctime> #define clr( x , y ) memset(x,y,sizeof(x)) #define cls( x ) memset(x,0,sizeof(x)) #define pr( x ) cout << #x << " = " << x << endl #define pri( x ) cout << #x << " = " << x << " " #define test( t ) int t ; cin >> t ; int kase = 1 ; while( t-- ) #define out( kase ) printf( "Case %d: " , kase++ ) #define sqr( x ) ( x * x ) #define mp make_pair #define pii pair<int,int> #define fi fist #define se second #define pb push_back using namespace std; typedef long long lint; const double eps = 1e-8 ; const int inf = 0x3f3f3f3f ; const long long INF = 0x3f3f3f3f3f3f3f3fLL ; const int fac[10] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 } ; const int N = 363000 ; int ch , cv ; int a[9] , b[9] , cost ; int fi , ed ; bool vis ; struct Node{ int x , w ; Node( int _x , int _w ):x(_x) , w(_w) {} bool operator < ( const Node &a )const { if ( w != a.w ) return w > a.w ; return x < a.x ; } } ; priority_queue<Node> q ; int A2int( int *a , int n ) { int res = 0 ; for ( int i = 0 ; i < n ; i++ ) { int tmp = a[i] ; for ( int j = 0 ; j < i ; j++ ) { if ( a[j] < a[i] ) tmp-- ; } res += fac[n-1-i] * tmp ; } return res ; } void int2A( int x , int *a , int n ) { bool flag[10] ; int j ; cls( flag ) ; for ( int i = 0 ; i < n ; i++ ) { int tmp = x / fac[n-1-i] ; for ( j = 0 ; j < n ; j++ ) { if ( !flag[j] ) { if ( !tmp ) break ; tmp -- ; } } a[i] = j , flag[j] = 1 ; x %= fac[n-i-1] ; } } void update( int num , int cos ) { if ( !vis[num] && cos < cost[num] ) cost[num] = cos, q.push( Node( num , cos ) ) ; } void bfs() { while ( !q.empty() ) { Node p = q.top() ; q.pop() ; if ( vis[p.x] ) continue ; vis[p.x] = true ; if ( p.x == ed ) { printf( "%d\n" , p.w ) ; break ; } int2A( p.x , a , 9 ) ; int k = 0 , tmp ; while ( a[k] > 0 ) k++ ; swap( a[k] , a[(k+1) % 9] ) ; //left tmp = A2int( a , 9 ) ; update( tmp , p.w + ch ) ; swap( a[k] , a[(k+1) % 9] ) ; swap( a[k] , a[(k+8) % 9] ) ; //right tmp = A2int( a , 9 ) ; update( tmp , p.w + ch ) ; swap( a[k] , a[(k+8) % 9] ) ; swap( a[k] , a[(k+3) % 9] ) ; //up tmp = A2int( a , 9 ) ; update( tmp , p.w + cv ) ; swap( a[k] , a[(k+3) % 9] ) ; swap( a[k] , a[(k+6) % 9] ) ; //down tmp = A2int( a , 9 ) ; update( tmp , p.w + cv ) ; swap( a[k] , a[(k+6) % 9] ) ; } } int main() { //freopen("my.in","r",stdin); //freopen("my.out","w",stdout); while ( ~scanf( "%d%d" ,&ch ,&cv ) ) { if ( !ch && !cv ) break ; for ( int i = 0 ; i < 9 ; i++ ) scanf( "%d" , a + i ) ; for ( int i = 0 ; i < 9 ; i++ ) scanf( "%d" , b + i ) ; fi = A2int( a , 9 ) ; ed = A2int( b , 9 ) ; cost[fi] = 0 ; while ( !q.empty() ) q.pop() ; cls( vis ) , clr( cost , inf ) ; q.push( Node( fi , 0 ) ) ; bfs() ; } return 0; }
I - Hidden Tree
DP我只认狗哥!相关文章推荐
- 优先队列(priority_queue)的C语言实现代码
- PHP 数据结构队列(SplQueue)和优先队列(SplPriorityQueue)简单使用实例
- Surrounded Regions
- Word Ladder, Gray Code
- UVA 11624
- HDU1495
- HDU2612 Find a way
- HDU1241 Oil Deposits
- Hdu2444二分图
- 最少步数BFS
- 转v_JULY_v的 BFS和DFS优先搜索算法
- 2015 寒假搜索专题 I - Meteor Shower(BFS)
- Same Tree
- E - Roads in the North
- DFS&BFS算法总结(1)
- Word Ladder I
- 图的BFS和DFS学习笔记
- [LeetCode] Binary Tree Level Order Traversal
- [LeetCode] Binary Tree Level Order Traversal II
- 数据挖掘:基于卡方的ChiMerge方法对数值离散化(稀有数据挖掘答案代码)