练习赛11 A-01背包 C暴力 D并查集+优先队列 F大数 G期望 (随机游走)H最短路变形

A
思路:01背包,尽可能装满背包,并且价值最大。只需要加上一个判断条件,保证每次都能够将 j 值装满。
Code:

#include 
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e6+66;
int v[AX];
LL w[AX];
LL dp[AX];
int main(){
    int T;
    int n , V;
    scanf("%d",&T);
    while( T-- ){
        scanf("%d%d",&n,&V);
        for( int i = 1 ; i <= n ; i++ ){
            scanf("%lld",&w[i]);
        }
        for( int i = 1 ; i <= n ; i++ ){
            scanf("%d",&v[i]);
        }
        memset( dp , 0 , sizeof(dp) );

        for( int i = 1 ; i <= n ; i++ ){
            for( int j = V ; j >= v[i] ; j-- ){
                if( dp[j-v[i]] || j == v[i] ) 
                dp[j] = max( dp[j] , dp[j-v[i]] + w[i] ) ;
            }
        }
        int j = V;
        int VV = 0;

        LL ibest = 0;
        for( int i = V ; i > 0 ; i-- ){
            if(dp[i] > ibest){
                ibest = dp[i];
                VV = i;
            }
        }
        printf("%lld %d\n",ibest,VV);
    }
    return 0 ;
}

C
题意:给你一个数字 ,你的任务是找一个最小的正整数 N,使得它的数位之积等于 Q
,如果不存在,请输出-1.
思路:每位只可能是2-9(1除外),每次尽可能大的取因子(2-9)如果不能整除就输出-1,
最后排序输出即可。
坑点就是0输出10,而不是-1.。。。。
Code:

#include 
#define LL long long 
using namespace std;
const int AX = 1e4+6;
int res[AX];
int n;
int cnt;

int main(){
    int T;
    scanf("%d",&T);
    while( T-- ){
        scanf("%d",&n);
        if( n == 1 ){
            printf("1\n"); continue;
        }else if( n == 0 ){
            printf("10\n"); continue;
        }
        cnt = 0;
        int falg = 1 ;
        while( n > 1 ){
            int f = 0 ;
            for( int i = 9 ; i >= 2 ; i-- ){
                while( n % i == 0 ){
                    res[cnt ++ ] = i;
                    n /= i ;
                    f = 1 ;
                }
            }      
            if( !f && n > 1 ) { falg = 0 ; break; }
        }
        if( falg == 0 ){
            printf("-1\n");
            continue;
        }
        sort( res , res + cnt ) ;
        for(int i = 0 ; i < cnt ; i++ ){
            printf("%d",res[i]);
        }printf("\n");
    }
    return 0;
}

D
题意:每次将最小的两个合并,并且编号采用较小的,给出m个询问,第t次之后Q的编号。
思路:并查集+模拟
优先队列id排序写反了,wa了超级久!!!
Code:

#include 
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e6+66;
int t, Q;
struct Node{
    int id ;
    int v;
    bool friend operator < ( const Node &a , const Node &b ){
        return ( a.v > b.v || ( a.v == b.v && a.id > b.id ) );
    }
}a[AX];
int pre[AX];

int find( int x ){
    //return x == pre[x] ? pre[x] : pre[x] = find(pre[x]);
    if( x == pre[x] ) return pre[x];
    return pre[x] = find(pre[x]);
}

int main(){
    int T;
    scanf("%d",&T);
    int n , m ;
    priority_queue q;
    while( T-- ){
        while( !q.empty() )  q.pop();
        scanf("%d%d",&n,&m);
        for( int i = 1 ; i <= n ; i++ ){
            scanf("%d",&a[i].v);
            a[i].id = i ;
            pre[i] = i ;
            q.push(a[i]);
        }
        int j = 0 ;
        for( int i = 0 ; i < m ; i++ ){
            scanf("%d%d",&t,&Q);
            for( ; j < t ; j++ ){
                Node x = q.top();
                q.pop();
                Node y = q.top();
                q.pop();
                Node tmp ;
                tmp.v = x.v + y.v;
                tmp.id = min( x.id , y.id );
                q.push(tmp);
                int xx = find(x.id);
                int yy = find(y.id);
                if( xx < yy ){
                    pre[yy] = xx;
                }else pre[xx] = yy;
            }
            //cout << find(Q) << endl;
            printf("%d\n",find(Q));
        }
    }
    return 0 ;
}

F
题意:输出相反数。
思路:最坑的题。。用java才过。
Code:

import java.util.*;
import java.math.*;
public class Main{
    public static void main(String[] args){
        Scanner cin = new Scanner(System.in);
        BigDecimal a , b , c ;
        int m;
        m = cin.nextInt();
        while(m>0){
            m = m - 1 ;
            a = cin.nextBigDecimal();
            b = new BigDecimal("0");
            b = b.subtract(a) ;
            System.out.println(b);
        }
    }
}

G
题意:从1到n,每次可能往回走,也可能往前走,问距离期望的平方。
思路:随机走在二维上距离的期望是n,在一维上距离 期望的平方 和二维的一样也是n

Code:

#include 
#define LL long long 
using namespace std;


int main(){
    int T;
    scanf("%d",&T);
    int n ;
    while( T-- ){

        scanf("%d",&n);
        printf("%.6lf\n",(double)n);
    }
    return 0;
}

H
题意:就是给n个点,m条边,这个边是每条路的高度(0,1,2),0不能走,可以给0添加高度值2,1,给1添加1,0。
要求路径必须是只能上升一次,也就是111222这样的1,2都可以没有。。问最少添加多少高度可以从1到达n。
思路:路径是111222这样的,所以从1开始将只走高度为1的边,0加上1,2不走。
再从n走向1只走高度为2的,0加上2,1加上1.然后取二者加和的最小值。

Code:

#include 
#define LL long long    
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 4e6+66;
typedef pair<int,int>P;
struct Node{
    int v , h ;
    int next1 ;
}G[AX];
int head[AX];
int tot ;
void addEdge( int u , int v , int h ){
    G[++tot].v = v ; G[tot].h = h ; G[tot].next1 = head[u];
    head[u] = tot ;
    G[++tot].v = u ; G[tot].h = h ; G[tot].next1 = head[v];
    head[v] = tot ; 
}
int vis[AX];
int n , m ;

int dis[AX];
int dis_inv[AX];

priority_queue< P , vector

, greater

>q; void dijstra(){ memset( dis, INF , sizeof(dis) ) ; q.push(P(0,1)); dis[1] = 0 ; while( !q.empty() ){ int u = q.top().second; int val = q.top().first; q.pop(); if( vis[u] ) continue; vis[u] = 1 ; if( val > dis[u] ) continue; for( int i = head[u] ; ~i ; i = G[i].next1 ){ int v = G[i].v ; if( G[i].h > 1 ) continue; if( dis[v] > dis[u] + 1 - G[i].h ){ dis[v] = dis[u] + 1 - G[i].h ; q.push(P( dis[v] , v )); } } } } void dijstra_inv(){ memset( dis_inv, INF , sizeof(dis_inv) ) ; q.push(P(0,n)); dis_inv[n] = 0 ; while( !q.empty() ){ int u = q.top().second; int val = q.top().first; q.pop(); if( vis[u] ) continue; vis[u] = 1 ; if( val > dis_inv[u] ) continue; for( int i = head[u] ; ~i ; i = G[i].next1 ){ int v = G[i].v ; if( dis_inv[v] > dis_inv[u] + 2 - G[i].h ){ dis_inv[v] = dis_inv[u] + 2 - G[i].h ; q.push(P( dis_inv[v] , v )); } } } } int main(){ int T; scanf("%d",&T); int u , v , h ; while( T-- ){ tot = 0 ; memset( head , -1 , sizeof(head) ); memset( vis , 0 , sizeof(vis) ); scanf("%d%d",&n,&m); for( int i = 0 ; i < m ; i++ ){ scanf("%d%d%d",&u,&v,&h); addEdge( u , v , h ); } dijstra(); memset( vis , 0 , sizeof(vis) ); dijstra_inv(); int res = INF; for( int i = 1 ; i <= n ; i++ ){ res = min( res , dis[i] + dis_inv[i] ); } printf("%d\n",res); } return 0 ; }

你可能感兴趣的:(数学-公式,贪心,大数,DP,最短路,STL,并查集)