Round B APAC Test 2016

本文针对CodeJam竞赛中的四个问题提供了解决方案,包括路径寻找、齿轮比率计算、gNumber游戏策略及子序列计数等问题,并提供了详细的算法思路及C++实现代码。

题目链接:https://code.google.com/codejam/contest/10214486/dashboard

Problem A

There are N cities in Chelsea's state (numbered starting from 1, which is Chelsea's city), and M bidirectional roads directly connect them. (A pair of cities may even be directly connected by more than one road.) Because of changes in traffic patterns, it may take different amounts of time to use a road at different times of day, depending on when the journey starts. (However, the direction traveled on the road does not matter -- traffic is always equally bad in both directions!) All trips on a road start (and end) exactly on the hour, and a trip on one road can be started instantaneously after finishing a trip on another road.

Chelsea loves to travel and is deciding where to go for her winter holiday trip. She wonders how quickly she can get from her city to various other destination cities, depending on what time she leaves her city. (Her route to her destination may include other intermediate cities on the way.) Can you answer all of her questions?

Input

The first line of the input gives the number of test cases, T. T test cases follow.

The first line of each test case contains three integers: the number N of cities, the number M of roads, and the number K of Chelsea's questions.

2M lines -- M pairs of two lines -- follow. In each pair, the first line contains two different integers x and y that describe one bidirectional road between the x-th city and the y-th city. The second line contains 24 integers Cost[t] (0 ≤ t ≤ 23) that indicate the time cost, in hours, to use the road when departing at t o'clock on that road. It is guaranteed that Cost[t] ≤ Cost[t+1]+1 (0 ≤ t ≤ 22) and Cost[23] ≤ Cost[0]+1.

Then, an additional K lines follow. Each contains two integers D and S that comprise a question: what is the fewest number of hours it will take to get from city 1 to city D, if Chelsea departs city 1 at S o'clock?

思路:问题的关键在于可能不可能先停留在原地一会儿之后出发反而更早到达别的地方。实际上由条件:Cost[t] ≤ Cost[t+1]+1可知这是不可能的,所以仍然是一个最短路问题。那么只要预求出从时间0~23的结点1出发,到达所有其他结点的最短路,然后进行查找即可。

#include <cstdio>
#include <queue>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 505
int s[N][N][25],n,m,q,T;
int dis[N][25],used[N];
int relax(int b,int x,int y,int w){
    if(dis[x][b] + w < dis[y][b]){
        dis[y][b] = dis[x][b] + w;
        return 1;
    }
    return 0;
}
void spfa(int b){//b时刻从1出发
    dis[1][b] = 0;
    queue<int> q;
    memset(used, 0, sizeof(used));
    q.push(1);
    used[1] = 1;
    while(!q.empty()){
        int now = q.front();
        q.pop();
        used[now] = 0;
        for(int i = 1;i<=n;i++)
            if(s[now][i][(dis[now][b]+b)%24]!=0x3fffffff)
                if(relax(b,now,i,s[now][i][(dis[now][b]+b)%24]) && !used[i]){
                    used[i] = 1;
                    q.push(i);
                }
    }
}
int main(){
    scanf("%d",&T);
    int a,b,x;
    for(int c = 1;c<=T;c++){
        scanf("%d %d %d",&n,&m,&q);
        for(int i = 1;i<=n;i++)
            for(int j = 1;j<=n;j++)
                for(int k = 0;k<24;k++)
                    s[i][j][k] = (i==j)?0:0x3fffffff;
        for(int i = 1;i<=n;i++)
            for(int j = 0;j<24;j++)
                dis[i][j] = 0x3fffffff;
        while(m--){
            scanf("%d %d",&a,&b);
            for(int i = 0;i<24;i++){
                scanf("%d",&x);
                s[a][b][i] = s[b][a][i] = min(s[a][b][i], x);
            }
        }
        for(int i = 0;i<24;i++)
            spfa(i);
        printf("Case #%d:",c);
        while(q--){
            scanf("%d %d",&a,&b);
            if(dis[a][b]==0x3fffffff)
                printf(" -1");
            else
                printf(" %d",dis[a][b]);
        }
        printf("\n");
    }
    return 0;
}


Problem B

A typical mountain bike has two groups of gears: one group connected to the pedals, and one group connected to the rear tire. A gear group consists of many gears, which usually have different numbers of teeth. A chain connects one of the gears in the pedal gear group to one of the gears in the tire gear group, and this determines the ratio between the cyclist's pedaling speed and the tire speed. For example, if the chain connects a gear with 5 teeth on the pedals to a gear with 10 teeth on the tires, the ratio will be 1/2, since the cyclist needs to make the pedal gear rotate twice to make the tire rotate once. The cyclist can change the chain to connect any one gear from the pedal group to any one gear from the tire group.

You have just bought a special new mountain bike with three groups of gears: one connected to the pedals, one connected to the tire, and one extra group in between. This mountain bike has two chains; the first chain must always connect one gear from the pedal gear group to one gear on the extra gear group, and the second chain must always connect one gear from the extra gear group to one gear on the tire gear group. Moreover, the two chains cannot both use the same gear from the extra gear group.

Given the numbers of teeth on the available gears on the pedals, extra, and tire groups, is it possible to make the ratio (between pedaling speed and tire speed) be exactly P/Q? For a given set of gears, you may need to answer multiple such questions.

Input

The first line of the input gives the number of test cases, T. T test cases follow. Each begins with one line with 3 integers Np, Ne, and Nt, representing the numbers of gears on the pedals, extra, and tire groups. Then, three more lines follow. These contain Np, Ne, and Nt integers, respectively, representing the numbers of teeth on the different gears on the pedals, extra, and tire gear groups, respectively. (It is guaranteed that the numbers of teeth on the gears within a group are all distinct.) The next line after that consists of one integer, M, the number of questions. Finally, there are M lines, each with 2 integers, P and Q, representing the target ratio. (It is not guaranteed that this ratio is a reduced fraction.)

题意:翻译一下题意就是,给定三个集合A,B,C(每个集合不超过2000个元素,每个元素不超过10000),还有两个整数P和Q(不超过10^9),问能否从A和C中各选出一个元素a和c,B中选出两个元素b1和b2,使得(a/b1)*(b2/c) = p/q。

思路:首先枚举b1/b2的值,然后枚举AC集合的元素对,求出其对应的b1/b2的值是否出现过。用set<pair<int,int>>来进行查找。时间复杂度是O(n*n*logn)。

#include <cstdio>
#include <set>
#include <unordered_set>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 2005
int T,a,b,c,m;
long long p,q;
int A[N],B[N],C[N];
set<pair<int, int>> hh;
long long gcd(long long a,long long b){
    return !b ? a : gcd(b, a%b);
}
bool solve(){
    for(int i = 0;i<a;i++)
        for(int j = 0;j<c;j++){
            long long x = p*C[j];
            long long y = q*A[i];
            long long tmp = gcd(x, y);
            x /= tmp;
            y /= tmp;
            if(x>10000 || y>10000)
                continue;
            if(hh.find(make_pair((int)x, (int)y)) != hh.end())
                return true;
        }
    return false;
}
int main(){
    scanf("%d",&T);
    for(int z = 1;z<=T;z++){
        scanf("%d %d %d",&a,&b,&c);
        for(int i = 0;i<a;i++)
            scanf("%d",&A[i]);
        for(int i = 0;i<b;i++)
            scanf("%d",&B[i]);
        for(int i = 0;i<c;i++)
            scanf("%d",&C[i]);
        
        hh.clear();
        for(int i = 0;i<b;i++)
            for(int j = i+1;j<b;j++){
                int tmp = (int)gcd(B[i], B[j]);
                hh.insert(make_pair(B[i]/tmp, B[j]/tmp));
                hh.insert(make_pair(B[j]/tmp, B[i]/tmp));
            }
        printf("Case #%d:\n",z);
        scanf("%d",&m);
        while(m--){
            scanf("%lld %lld",&p,&q);
            long long tmp = gcd(p,q);
            p /= tmp;
            q /= tmp;
            if(solve())
                printf("Yes\n");
            else
                printf("No\n");
        }
    }
    return 0;
}

Problem C. gNumbers

Googlers are crazy about numbers and games, especially number games! Two Googlers, Laurence and Seymour, have invented a new two-player game based on "gNumbers". A number is a gNumber if and only if the sum of the number's digits has no positive divisors other than 1 and itself. (In particular, note that 1 is a gNumber.)

The game works as follows: First, someone who is not playing the game chooses a starting number N. Then, the two players take turns. On a player's turn, the player checks whether the current number C is a gNumber. If it is, the player loses the game immediately. Otherwise, the player chooses a prime factor P of C, and keeps dividing C by P until P is no longer a factor of C. (For example, if the current number were 72, the player could either choose 2 and repeatedly divide by 2 until reaching 9, or choose 3 and repeatedly divide by 3 until reaching 8.) Then the result of the division becomes the new current number, and the other player's turn begins.

Laurence always gets to go first, and he hates to lose. Given a number N, he wants you to tell him which player is certain to win, assuming that both players play optimally.

Input

The first line of the input gives the number of test cases, T. T test cases follow; each consists of a starting number N.

Output

For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the winner's name: either Laurence or Seymour.

题意:定义了gNumber(各位数字和为质数,1也算),初始一个数,如果是gNumber则输,不是的话可以选择其任意一个质因子,一直除知道没法除未知,交换。问谁有必胜策略。

思路:一开始找规律,发现找不到。搜题解看到直接暴力就能过。于是直接暴力,但是少考虑了大于根号n的那个质因子导致一直错误。具体来说,对于一个数n来说,其可能出现一个质因子大于根号n,如果有,最多只有一个(显然)。所以只需要在2~根号n范围内的质数中扫,然后保存一个剩余的数,如果最后不等于1,那么就是这个大于根号n的质因子。

当然,后来看到提交页面排名第一的做法,实际上还可以用动归状态压缩优化。首先在n的范围内,n的质因子个数少于20个(没仔细算,就是看看2*3*5多少个开始大于10的15次方)。举例来说,将n写成a^s1 * b^s2 *c^s3...g^s6,用第一位表示a^s1,第二位表示a^s2等等等。从0遍历到1<<6,比如i,dp[i]表示i对应的数是否为必胜态,由于i的后继都已经算出(因为i中去掉每个位上的1必然比i小),所以可以从那些位置推得dp[i]的值)。最后看看dp[全1]是1还是0即可。

#include <cstdio>
#include <set>
#include <unordered_set>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 40000000
int T,len = 0;
long long prime[2000000],n;
bool hh[160];
bool s[N];
void init(){
    memset(s, false, sizeof(s));
    memset(hh, false, sizeof(hh));
    hh[1] = true;
    for(long long i = 2;i*i<=1000000000000000;i++)
        if(!s[i]){
            prime[len++] = i;
            for(long long j = i;j*j<=1000000000000000;j+=i)
                s[j] = true;
            if(i<160)//按照输入范围15*9就够了
                hh[i] = true;
        }
}
bool testG(long long x){//判断一个数是否为gNumber
    int sum = 0;
    while(x){
        sum += x%10;
        x /= 10;
    }
    return hh[sum];
}
bool win(long long x){
    if(testG(x))
        return false;
    long long left = x;//这个left有没有考虑进去是关键,错了很多次
    for(int i = 0;i<len && prime[i]*prime[i]<=x;i++)
        if(x%prime[i] == 0){
            long long next = x;
            while(next % prime[i] == 0)
                next /= prime[i];
            while(left % prime[i] == 0)
                left /= prime[i];
            if(!win(next))
                return true;
        }
    if(left!=1 && !win(x/left))
        return true;
    return false;
}
int main(){
    init();
    scanf("%d",&T);
    for(int z = 1;z<=T;z++){
        scanf("%lld",&n);
        if(win(n))
            printf("Case #%d: Laurence\n",z);
        else
            printf("Case #%d: Seymour\n",z);
    }
    return 0;
}


Problem D. Albocede DNA

The DNA of the Albocede alien species is made up of 4 types of nucleotides: a, b, c, and d. Different Albocedes may have different sequences of these nucleotides, but any Albocede's DNA sequence obeys all of the following rules:

It contains at least one copy of each of a, b, c, and d.
All as come before all bs, which come before all cs, which come before all ds.
There are exactly as many 'a's as 'c's.
There are exactly as many 'b's as 'd's.
For example, abcd and aabbbccddd are valid Albocede DNA sequences. acbd, abc, and abbccd are not.

The Albocede-n is an evolved species of Albocede. The DNA sequence of an Albocede-n consists of one or more valid Albocede DNA sequences, concatenated together end-to-end. For example, abcd and aaabcccdaabbbccdddabcd are valid Albocede-n DNA sequences. (Observe that a valid Albocede-n DNA sequence is not necessarily also a valid Albocede DNA sequence.)

From one of your alien expeditions, you retrieved an interesting sequence of DNA made up of only as, bs, cs, and ds. You are interested in how many of the different subsequences of that sequence would be valid Albocede-n DNA sequences. (Even if multiple different selections of nucleotides from the sequence produce the same valid subsequence, they still all count as distinct subsequences.) Since the result may be very large, please find it modulo 1000000007 (109 + 7).

Input

The first line of the input gives the number of test cases, T. Each of the next T lines contains a string S that consists only of the characters a, b, c, and d.

题意:给定一个只含有abcd的串,求满足条件的子序列个数。

思路:动态规划。dp[i][j][k][s]表示前s[1...i]中,处理到还有j个a,k个b而且最后一个处理的是s(s取0~3,0表示a,1表示b,2表示c,d表示d)。

一开始没有加第四维,是错误的。比如处理dp[x][1][2]的时候,它可能最后已经添加c了,那么我们不能再在后面添加b了。

其中一个bug调试了近一个小时(一开始数组维度开的dp[2][N/2][N/2][4],这样写循环的时候用j<i判断则会越界。虽然N/2足够了(只需要在判断的地方改一下即可),但是这样的内存也够了。

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 505
#define M 1000000007
char s[N];
int dp[2][N][N][4];
int T;
int main(){
    scanf("%d",&T);
    for(int z = 1;z<=T;z++){
        memset(dp, 0, sizeof(dp));
        dp[0][0][0][3] = 1;
        scanf("%s",s+1);
        int p,q;
        for(int i = 1;s[i];i++){
            q = i&1;
            p = 1-q;
            memcpy(dp[q], dp[p], sizeof(dp[p]));
            if(s[i] == 'a'){
                for(int j = 2;j<=i;j++)
                    dp[q][j][0][0] += dp[p][j-1][0][0] , dp[q][j][0][0]%=M;
                dp[q][1][0][0] += dp[p][0][0][3] , dp[q][1][0][0]%=M;
            }else if(s[i] == 'b'){
                for(int k = 1;k<i;k++){
                    for(int j = 2;j<=i;j++)
                        dp[q][k][j][1] += dp[p][k][j-1][1] , dp[q][k][j][1]%=M;
                    dp[q][k][1][1] += dp[p][k][0][0] , dp[q][k][1][1]%=M;
                }
            }else if(s[i] == 'c'){
                for(int j = 0;j<i;j++)
                    for(int k = 1;k<i;k++){
                        dp[q][j][k][2] += dp[p][j+1][k][2] , dp[q][j][k][2]%=M;
                        dp[q][j][k][2] += dp[p][j+1][k][1] , dp[q][j][k][2]%=M;
                    }
            }else{
                for(int j = 0;j<i;j++){
                    dp[q][0][j][3] += dp[p][0][j+1][3] , dp[q][0][j][3]%=M;
                    dp[q][0][j][3] += dp[p][0][j+1][2] , dp[q][0][j][3]%=M;
                }
            }
        }
        printf("Case #%d: %d\n",z,dp[q][0][0][3]%M-1);
        
    }
    return 0;
}


close all; clc; clear; tic; %% 01 鍙傛暟閰嶇疆 W = 1280; H = 720; save_folder = "data/project"; mkdir(save_folder); save_file_csv = strcat(save_folder, "/","patterns.csv"); % 鐢ㄤ簬鍐欏叆鍒版姇褰变华 n = 4; % 鏍奸浄鐮佷綅鏁� % 鐩哥Щ鍙傛暟 N = 12; % 鐩哥Щ姝ユ暟 A = 130; B = 90; TW = W / (2 ^ n); TH = H / (2 ^ n); %% 02 鐢熸垚鐩哥Щ娉曞浘鍍� [~, patterns_phaseshift_X] = m_make_phase_shift_patterns(A, B, TW, N, W, H); [~, temp_Y] = m_make_phase_shift_patterns(A, B, TH, N, H, W); patterns_phaseshift_Y = zeros(N, H, W); for i = 1: N patterns_phaseshift_Y(i, :, :) = squeeze(temp_Y(i, :, :))'; end %% 03 鐢熸垚鏍奸浄鐮佸浘鍍忥細X鏂瑰悜 patterns_graycode_X = m_make_gray_code_patterns(n, W, H); temp_Y = m_make_gray_code_patterns(n, H, W); [num, H, W] = size(patterns_graycode_X); patterns_graycode_Y = zeros(num, H, W); for i = 1: num patterns_graycode_Y(i, :, :) = squeeze(temp_Y(i, :, :))'; end %% 04 鍐欏叆鍥惧儚 idx = 0; file = fopen(save_file_csv, "w+"); % 鍐欏叆鐩哥Щ鍥炬 X for i = 1: N idx = idx + 1; % 鍐欏叆鍥剧墖 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); disp("鍐欏叆鏂囦欢鍒�:" + save_file_img); img = squeeze(patterns_phaseshift_X(i, :, :)); imwrite(img, save_file_img); % 鍐欏叆csv鏂囦欢 img_row = squeeze(img(1, :)) * 255.; for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end % 鍐欏叆鏍奸浄鐮佺▼搴� X for i = 1: num idx = idx + 1; % 鍐欏叆鍥惧儚 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); disp("鍐欏叆鏂囦欢鍒�:" + save_file_img); img = squeeze(patterns_graycode_X(i, :, :)); imwrite(img, save_file_img); % 鍐欏叆鍥惧儚 img_row = squeeze(img(1, :)); for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end % 鍐欏叆鐩哥Щ鍥炬 Y for i = 1: N idx = idx + 1; % 鍐欏叆鍥剧墖 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); disp("鍐欏叆鏂囦欢鍒�:" + save_file_img); img = squeeze(patterns_phaseshift_Y(i, :, :)); imwrite(img, save_file_img); % 鍐欏叆csv鏂囦欢 img_row = squeeze(img(1, :)) * 255.; for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end % 鍐欏叆鏍奸浄鐮佺▼搴� Y for i = 1: num idx = idx + 1; % 鍐欏叆鍥惧儚 save_file_img = strcat(save_folder, "/", int2str(idx), ".bmp"); disp("鍐欏叆鏂囦欢鍒�:" + save_file_img); img = squeeze(patterns_graycode_Y(i, :, :)); imwrite(img, save_file_img); % 鍐欏叆鍥惧儚 img_row = squeeze(img(1, :)); for w = 1: W fprintf(file, strcat(int2str(round(img_row(w))), ",")); end fprintf(file, "\n"); end disp("鍐欏叆瀹屾垚"); fclose(file); toc;close all; clc; clear; tic; %% 01 鍙傛暟閰嶇疆 calib_folder = "data/calib"; N = 12; n = 4; num = n + 2; B_min = 10; % 浣庝簬杩欎釜璋冨埗搴︾殑鎴戜滑灏辫涓哄畠鐨勭浉浣嶄俊鎭笉鍙潬 IT = 0.5; % 鏍奸浄鐮侀槇鍊� win_size = 7; % 涓�兼护娉㈢獥鍙eぇ灏� W = 1280; H = 720; points_per_row = 7; points_per_col = 6; w = 2; load("data/calib/camera_imagePoints.mat"); [~, ~, calib_num] = size(imagePoints); prjPoints = zeros(size(imagePoints)); %% 02 鏍囧畾鎶曞奖浠�佺浉鏈� for calib_idx = 1: calib_num disp(calib_idx); data_folder = calib_folder + "/" + num2str(calib_idx); %% 02 杩戜技鏌ョ湅鍥惧儚鍦嗗績 img = 255 - imread(data_folder + "/18.bmp"); for i = 1: points_per_row * points_per_col xy = imagePoints(i, :, calib_idx); x = round(xy(1)); y = round(xy(2)); img(y, x) = 255; end figure(); mesh(img); %% 03 瑙\Y鐩镐綅 files_phaseShiftX = cell(1, N); idx = 1; for i = 1: N files_phaseShiftX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end files_grayCodeX = cell(1, num); for i = 1: num files_grayCodeX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end files_phaseShiftY = cell(1, N); for i = 1: N files_phaseShiftY{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end files_grayCodeY = cell(1, num); for i = 1: num files_grayCodeY{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end [phaX, difX] = m_calc_absolute_phase(files_phaseShiftX, files_grayCodeX, IT, B_min, win_size); [phaY, difY] = m_calc_absolute_phase(files_phaseShiftY, files_grayCodeY, IT, B_min, win_size); phaX = phaX * W; phaY = phaY * H; for i = 1: points_per_row * points_per_col xy = imagePoints(i, :, calib_idx); x = xy(1); y = xy(2); x_round = round(x); y_round = round(y); % 瀵箈銆亂闄勮繎瀵圭浉浣嶈繘琛屾牱鏉℃洸绾挎彃鍊� xs = zeros(1, 2 * w + 1); ys = zeros(1, 2 * w + 1); phas_x = zeros(1, 2 * w + 1); phas_y = zeros(1, 2 * w + 1); ii = 1; for j = - 1 * w: w xs(1, ii) = x_round + j; ys(1, ii) = y_round + j; phas_x(1, ii) = phaX(y_round, xs(1, ii)); phas_y(1, ii) = phaY(ys(1, ii), x_round); ii = ii + 1; end pha_x = spline(xs, phas_x, x); pha_y = spline(ys, phas_y, y); prjPoints(i, :, calib_idx) = [pha_x, pha_y]; end end save(calib_folder + "\projector_imagePoints.mat", 'prjPoints'); toc;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 3D recosntruction with the calibrated triangular stereo model. % Related Reference: % "Calibration of fringe projection profilometry: A comparative review" % Shijie Feng, Chao Zuo, Liang Zhang, Tianyang Tao, Yan Hu, Wei Yin, Jiaming Qian, and Qian Chen % last modified on 07/27/2020 % by Shijie Feng (Email: shijiefeng@njust.edu.cn) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Clear everything existing. clc; clear; close all; data_folder = "data/model"; N = 12; n = 4; num = n + 2; B_min = 10; % 浣庝簬杩欎釜璋冨埗搴︾殑鎴戜滑灏辫涓哄畠鐨勭浉浣嶄俊鎭笉鍙潬 IT = 0.5; % 鏍奸浄鐮侀槇鍊� win_size = 7; % 涓�兼护娉㈢獥鍙eぇ灏� %% step1: input parameters width = 1280; % camera width height = 1024; % camera height prj_width = 1280; % projector width %camera: Projection matrix Pc load('CamCalibResult.mat'); Kc = KK; % 鐩告満鍐呭弬 Ac = Kc * [Rc_1, Tc_1]; %projector: Projection matrix Pp load('PrjCalibResult.mat'); Kp = KK; % 鎶曞奖浠唴鍙� Ap = Kp * [Rc_1, Tc_1]; %% step2: 璇诲彇娴嬭瘯鍥剧墖骞朵笖璁$畻涓夌淮閲嶅缓 % % 鏉$汗棰戠巼64锛屼篃鏄棿璺濓紙涓�涓懆鏈熺敱64涓儚绱犵粍鎴愶級鐢ㄤ簬璁$畻缁濆鐩镐綅锛岄鐜�1銆�8鐢ㄤ簬鍖呰9鐩镐綅灞曞紑 % f = 64; % 鏉$汗棰戠巼锛堝崟涓懆鏈熸潯绾圭殑鍍忕礌涓暟锛夛紝鍗砅 % load('up_test_obj.mat'); % up_test_obj = up_test_obj / f; % 灏嗙浉浣嶅綊涓�鍖栧埌[0, 2pi]涔嬮棿 % % figure; imshow(up_test_obj / (2 * pi)); colorbar; title("鐩镐綅鍥�, freq=" + num2str(f)); % figure; mesh(up_test_obj); colorbar; title("鐩镐綅鍥�, freq=" + num2str(f)); % % % 璁$畻鎶曞奖浠潗鏍� % x_p = up_test_obj / (2 * pi) * prj_width; idx = 1; files_phaseShiftX = cell(1, N); for i = 1: N files_phaseShiftX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end files_grayCodeX = cell(1, num); for i = 1: num files_grayCodeX{i} = strcat(data_folder, "/", int2str(idx), ".bmp"); idx = idx + 1; end [phaX, difX] = m_calc_absolute_phase(files_phaseShiftX, files_grayCodeX, IT, B_min, win_size); up_test_obj = phaX * 2 * pi; x_p = phaX * prj_width; % 3D閲嶅缓 Xws = nan(height, width); Yws = nan(height, width); Zws = nan(height, width); for y = 1:height for x = 1:width if ~(up_test_obj(y, x) == 0) uc = x - 1; vc = y - 1; up = (x_p(y, x) - 1); % Eq. (32) in the reference paper. A = [Ac(1,1) - Ac(3,1) * uc, Ac(1,2) - Ac(3,2) * uc, Ac(1,3) - Ac(3,3) * uc; Ac(2,1) - Ac(3,1) * vc, Ac(2,2) - Ac(3,2) * vc, Ac(2,3) - Ac(3,3) * vc; Ap(1,1) - Ap(3,1) * up, Ap(1,2) - Ap(3,2) * up, Ap(1,3) - Ap(3,3) * up]; b = [Ac(3,4) * uc - Ac(1,4); Ac(3,4) * vc - Ac(2,4); Ap(3,4) * up - Ap(1,4)]; XYZ_w = inv(A) * b; Xws(y, x) = XYZ_w(1); Yws(y, x) = XYZ_w(2); Zws(y, x) = XYZ_w(3); end end end % 鐐逛簯鏄剧ず xyzPoints(:, 1) = Xws(:); xyzPoints(:, 2) = Yws(:); xyzPoints(:, 3) = Zws(:); ptCloud = pointCloud(xyzPoints); xlimits = [min(Xws(:)), max(Xws(:))]; ylimits = [min(Yws(:)), max(Yws(:))]; zlimits = ptCloud.ZLimits; player = pcplayer(xlimits, ylimits, zlimits); xlabel(player.Axes,'X (mm)'); ylabel(player.Axes,'Y (mm)'); zlabel(player.Axes,'Z (mm)'); view(player,ptCloud); 这是代码主体部分,接下来给出功能函数function [pha_absolute, dif] = m_calc_absolute_phase(files_phaseShift, files_grayCode, IT, B_min, win_size) [~, N] = size(files_phaseShift); [pha_wrapped, B] = m_calc_warppred_phase(files_phaseShift, N); [~, n] = size(files_grayCode); n = n - 2; % 鎶曞奖浜嗕竴榛戜竴鐧戒袱骞呭浘鐗� Ks = m_calc_gray_code(files_grayCode, IT, n); pha_absolute = pha_wrapped + 2 * pi .* Ks; % 璋冨埗搴︽护娉� B_mask = B > B_min; pha_absolute = pha_absolute .* B_mask; % 杈圭紭璺冲彉璇樊 [pha_absolute, dif] = m_filter2d(pha_absolute, win_size); % 褰掍竴鍖� pha_absolute = pha_absolute / (2 * pi * 2^ n); endfunction [Ks] = m_calc_gray_code(files, IT, n) % 01 璇诲彇姣忎竴寮犲浘鐗囪繘Is [~, num] = size(files); img = imread(files{1}); [h, w] = size(img); Is = zeros(num, h, w); for i = 1: num img = imread(files{i}); Is(i, :, :) = double(img); end % 02 璁$畻Is_Max銆両s_Min锛屽姣忎釜鐐硅繘琛岄槇鍊煎垽鏂� Is_max = max(Is); Is_min = min(Is); Is_std = (Is - Is_min) ./ (Is_max - Is_min); gcs = Is_std > IT; % 03 瀵规瘡涓儚绱犵偣锛岃绠楃紪鐮佸�糣 Vs_row = zeros(1, 2 ^ n, 'uint8'); codes = m_gray_code(n); for i = 1: 2 ^ n code = str2mat(codes(i)); %#ok<DSTRMT> V = 0; for j = 1: n V = V + str2num(code(j)) * 2^ (4 - j); %#ok<ST2NM> end Vs_row(1, i) = V; end % 04 寤虹珛 V - > K 鐨勬槧灏勮〃 V2K = containers.Map(); for K = 1: 2 ^ n V = Vs_row(1, K); V2K(int2str(V)) = K - 1; end Ks = zeros(h, w); for v = 1: h %disp(strcat("绗�", int2str(v), "琛�")); for u = 1: w % 涓嶉渶瑕佹渶鍚庨粦銆佺櫧涓ゅ箙鍥剧墖鐨勭紪鐮� gc = gcs(1: n, v, u); V = 0; for i = 1: n V = V + gc(i) * 2 ^ (4 - i); end % 涓昏鐨勬�ц兘鐡堕 Ks(v, u) = V2K(int2str(V)); end end end function [Ks] = m_calc_gray_code(files, IT, n) % 01 璇诲彇姣忎竴寮犲浘鐗囪繘Is [~, num] = size(files); img = imread(files{1}); [h, w] = size(img); Is = zeros(num, h, w); for i = 1: num img = imread(files{i}); Is(i, :, :) = double(img); end % 02 璁$畻Is_Max銆両s_Min锛屽姣忎釜鐐硅繘琛岄槇鍊煎垽鏂� Is_max = max(Is); Is_min = min(Is); Is_std = (Is - Is_min) ./ (Is_max - Is_min); gcs = Is_std > IT; % 03 瀵规瘡涓儚绱犵偣锛岃绠楃紪鐮佸�糣 Vs_row = zeros(1, 2 ^ n, 'uint8'); codes = m_gray_code(n); for i = 1: 2 ^ n code = str2mat(codes(i)); %#ok<DSTRMT> V = 0; for j = 1: n V = V + str2num(code(j)) * 2^ (4 - j); %#ok<ST2NM> end Vs_row(1, i) = V; end % 04 寤虹珛 V - > K 鐨勬槧灏勮〃 V2K = containers.Map(); for K = 1: 2 ^ n V = Vs_row(1, K); V2K(int2str(V)) = K - 1; end Ks = zeros(h, w); for v = 1: h %disp(strcat("绗�", int2str(v), "琛�")); for u = 1: w % 涓嶉渶瑕佹渶鍚庨粦銆佺櫧涓ゅ箙鍥剧墖鐨勭紪鐮� gc = gcs(1: n, v, u); V = 0; for i = 1: n V = V + gc(i) * 2 ^ (4 - i); end % 涓昏鐨勬�ц兘鐡堕 Ks(v, u) = V2K(int2str(V)); end end end %% 计算包裹相位 function [pha, B] = m_calc_warppred_phase(files, N) sin_sum = 0; cos_sum = 0; for k = 0: N - 1 Ik = m_imread(files{k + 1}); % 读取图片 Ik = m_filter2d(Ik); sin_sum = sin_sum + Ik * sin(2 * k * pi / N); cos_sum = cos_sum + Ik * cos(2 * k * pi / N); end % 根据计算相位、调制度 pha = atan2(sin_sum, cos_sum); B = sqrt(sin_sum .^ 2 + cos_sum .^ 2) * 2 / N; %% 尝试注释掉这段,自己从零实现一遍 % 为了将波折相位转为单个周期内单调递增 pha = - pha; pha_low_mask = pha <= 0; pha = pha + pha_low_mask .* 2. * pi; end %% 读取图片 function [img] = m_imread(file) img = imread(file); img = double(((img(:, :, 1)))); % 转换灰度图 end %% 高斯滤波 function [img] = m_filter2d(img) w = 3.; sigma = 1.; kernel = fspecial("gaussian", [w, w], sigma); img = imfilter(img, kernel, "replicate"); end% 滤波 function [pha_new, dif] = m_filter2d(pha, win_size) % 中值滤波(格雷码边缘处计算出现问题) pha_new = medfilt2(pha, [win_size, win_size]); % (剔除未编码区域) dif = pha - pha_new; endfunction [code] = m_gray_code(n) if (n < 1) disp("鏍奸浄鐮佹暟閲忓繀椤诲ぇ浜�0"); return; elseif (n == 1) % 浜х敓0銆�1 涓や釜鏁板瓧 code = ["0", "1"]; % 杩斿洖code else code_pre = m_gray_code(n - 1); [~, num] = size(code_pre); % 鍒濆鍖栦竴涓暟缁� code = repmat("", 1, num * 2); % step1锛氭瘡涓瓧绗︿覆鍓嶉潰閮�+0 idx = 0; for i = 1: num idx = idx + 1; code(idx) = "0" + code_pre(i); end % step2锛氱炕杞涓厓绱狅紝鍏朵綑鍙栧绉� for i = num: -1: 1 idx = idx + 1; code(idx) = "1" + code_pre(i); end end endfunction [patterns] = m_make_gray_code_patterns(n, W, H) codes = m_gray_code(n); % 灏嗗瓧绗︿覆鏍奸浄鐮佽浆鎹负鐭╅樀鏍煎紡 [~, num] = size(codes); codes_mat = zeros(n, num, 'int8'); for col = 1: num code_col = str2mat(codes(col)); %#ok<DSTRMT> for row = 1: n codes_mat(row, col) = str2num(code_col(row)); %#ok<ST2NM> end end W_per = round(W / num); % 姣忓紶鍥剧墖 patterns = zeros(n + 2, H, W, "uint8"); for idx = 1: n % 涓�琛屽浘鐗� row_one = zeros(1, W, "uint8"); % 姣忎釜鏍煎瓙 for i = 1 : num gray = codes_mat(idx, i); % 鏍煎瓙閲屾瘡涓儚绱� for w = 1: W_per row_one(1, (i - 1) * W_per + w) = gray; end end row_one = row_one * 255; pattern = repmat(row_one, H, 1); patterns(idx, :, :) = pattern; end % 鍏ㄩ粦銆佸叏鐧藉浘鐗囷紝鐢ㄤ簬纭畾姣忎釜鍍忕礌闃堝�� patterns(n + 2, :, :) = ones(H, W, 'uint8') * 255; end % 函数:生成相移条纹 function [Is, Is_img] = m_make_phase_shift_patterns(A, B, T, N, W, H) Is = cell(N, 1); Is_img = zeros(N, H, W); xs = 1: W; f_2pi = 1. / double(T) * 2. * pi; for k = 0: N - 1 Is{k + 1} = A + B * cos(f_2pi * xs + 2 * k / N * pi); Is_img(k + 1, :, :) = repmat(Is{k + 1} / 255., H, 1); end end 请一句一句的解释代码,我是小白
最新发布
09-19
### 回答问题 这段代码使用了 `sklearn.metrics` 模块中的评估指标函数来计算分类模型的性能。以下是代码的功能和解释: #### **代码功能** 1. **`accuracy_score`**: - 计算预测值与真实值之间的准确率(Accuracy)。 - 准确率定义为分类正确的样本数占总样本数的比例。 2. **`precision_score`**: - 计算分类模型的精确率(Precision)。 - 精确率定义为被预测为正类的样本中,实际为正类的比例。 3. **`recall_score`**: - 计算分类模型的召回率(Recall)。 - 召回率定义为所有实际为正类的样本中,被正确预测为正类的比例。 4. **`f1_score`**: - 计算 F1 分数(F1 Score),它是精确率和召回率的调和平均数。 - F1 分数综合考虑了精确率和召回率,适用于两类不平衡的情况。 5. **`np.round`**: - 将 `y_test` 和 `y_test_pred` 的值四舍五入到最近的整数(通常用于将概率预测转换为类别标签)。 6. **`zero_division=0`**: - 在计算精确率或召回率时,如果分母为 0,则返回 0 而不是抛出异常。 --- #### **代码示例** 以下是一个完整的代码示例: ```python from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score import numpy as np # 示例数据 y_test = np.array([0, 1, 1, 0, 1]) # 真实标签 y_test_pred = np.array([0.2, 0.7, 0.9, 0.4, 0.8]) # 预测概率 # 四舍五入预测概率为类别标签 y_test_rounded = np.round(y_test) y_test_pred_rounded = np.round(y_test_pred) # 计算评估指标 accuracy = accuracy_score(y_test_rounded, y_test_pred_rounded) precision = precision_score(y_test_rounded, y_test_pred_rounded, zero_division=0) recall = recall_score(y_test_rounded, y_test_pred_rounded, zero_division=0) f1 = f1_score(y_test_rounded, y_test_pred_rounded, zero_division=0) # 输出结果 print(f"Accuracy: {accuracy}") print(f"Precision: {precision}") print(f"Recall: {recall}") print(f"F1 Score: {f1}") ``` --- #### **运行结果** 假设输入数据如下: - `y_test = [0, 1, 1, 0, 1]` - `y_test_pred = [0.2, 0.7, 0.9, 0.4, 0.8]` 运行上述代码后,输出结果可能如下: ``` Accuracy: 1.0 Precision: 1.0 Recall: 1.0 F1 Score: 1.0 ``` --- ### 解释 1. **`np.round` 的作用**: - `y_test_pred` 是一个概率预测数组(如 `[0.2, 0.7, 0.9, 0.4, 0.8]`)。 - 使用 `np.round` 将其转换为二元类别标签(如 `[0, 1, 1, 0, 1]`)。 2. **评估指标的意义**: - **准确率(Accuracy)**:衡量整体分类的正确性。 - **精确率(Precision)**:衡量模型在预测为正类的样本中,有多少是真正的正类。 - **召回率(Recall)**:衡量模型在所有正类样本中,有多少被正确预测为正类。 - **F1 分数(F1 Score)**:综合考虑精确率和召回率,尤其适用于类别不平衡的情况。 3. **`zero_division=0` 的作用**: - 当某个类别没有预测为正类时,精确率或召回率的分母可能为 0。 - 设置 `zero_division=0` 可以避免在这种情况下抛出异常。 --- ### 报错原因总结 - 如果 `y_test` 或 `y_test_pred` 的值不是二元类别标签(如 0 和 1),则需要先将其转换为类别标签(通过 `np.round` 或其他方法)。 - 如果类别不平衡或某些类别未被预测到,可能会导致分母为 0 的问题,因此需要设置 `zero_division=0`。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值