【URAL 刷題記】URAL 1028 ~ URAL 1035

URAL 1028

/*
題意:求左下角點的個數。。。
題解:把點按照x座標排序,y軸建一棵樹狀數組即可。。
*/ 
#include<algorithm>
#include<cstdio>
using namespace std;

typedef pair<int,int>P;


const int MAXN=40000;
int T[MAXN];
void add(int x, int v){ for(; x<MAXN; x+=x&-x) T[x]+=v; }
int sum(int x){ int v=0; for(;x;x-=x&-x) v+=T[x]; return v; }

const int maxn=15010;

P A[maxn];
int res[maxn];
int n;

int main(){
//  freopen("in.txt","r",stdin);
    scanf("%d",&n);
    for(int i=0;i<n;++i){
        int x,y;scanf("%d%d",&x,&y); ++x,++y;
        A[i]=P(x,y);
    }
    sort(A,A+n);
    for%53C%"5�Fspan>(int i=0;i<n;++i){
        int x=sum(A[i].second);
        res[x] ++;
        add(A[i].second,1);
    }
    for(int i=0;i<n;++i)printf("%d\n",res[i]);
//  for(;;);
    return 0;
}

URAL 1029

/*
題意:求出從第一層樓到第m層樓的最少花費, i-1樓的k房間可以到i樓的k房間, 同一樓層相鄰的房間可以聯通(差1)
題解:直接對每一層往右往左刷一遍(因爲權值爲正,所以不可能繞彎。),上下更新一把即可。 
*/

#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

typedef long long LL;

const int maxn=10010;

int n,m;
int A[maxn][maxn], f[maxn][maxn], g[maxn][maxn];

void dfs(int d,int i,int j){
    if(i==0)return;
    if(g[i][j]!=j)dfs(d+1,i,g[i][j]); else dfs(d+1,i-1,j);
    printf("%d%c", j,d==0?'\n':' ');
}
void solve(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            scanf("%d",&A[i][j]);
    for(int j=1;j<=m;++j)
        f[0][j]=0;

    for(int i=1;i<=n;++i) {
        for(int j=1;j<=m;++j)
            f[i][j]=f[i-1][j]+A[i][j],g[i][j]=j;
        for(int j=m-1;j>=1;--j)
            if(f[i][j]>f[i][j+1]+A[i][j])
                f[i][j]=f[i][j+1]+A[i][j],g[i][j]=j+1;
        for(int j=2;j<=m;++j)
            if(f[i][j]>f[i][j-1]+A[i][j])
                f[i][j]=f[i][j-1]+A[i][j],g[i][j]=j-1;
    }
    int x=min_element(f[n]+1,f[n]+m+1)-f[n];
    dfs(0,n,x);
}

int main(){
//  freopen("in.txt","r",stdin);
    solve();
//  for(;;);
    return 0;
}

URAL 1030

/*
給出船隻和冰山的經緯度,求出它們之間的距離,並判斷其是否大於100
解法:
球面的距離公式:R*acos( sin(x1)*sin(x2)+cos(x1)*cos(x2)*cos(y1-y2) )/2;
這裏x是緯度,y是經度,計算之前所有的經緯度都要化爲弧度制
R=6875,題目裏有給

我是先把球座標系轉化爲三維座標系,然後求角度做的。。。。
https://en.wikipedia.org/wiki/Spherical_coordinate_system 
注意一下這裏有兩幅圖,角度表示是不同的。。。所以可能到時圖片公式不配套(Baidu百科好坑。。)
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;

const double EarthR=6875.0/2;
const double PI=acos(-1.0);

double sqr(double x){ return x*x; }

char s[4][10], t[4][10];

double getang(char *s){
    double res=0;
    char *p=strtok(s,"^'\"");
    res+=atoi(p);
    p=strtok(0,"^'\"");
    res+=atoi(p)/60.0;
    p=strtok(0,"^'\"");
    res+=atoi(p)/60.0/60.0;
    res=res/180.0*PI;
    return res;
}

double ang[4];
double x[2],y[2],z[2];

void solve(){
    scanf("%*s%*s%*s%*s%*s%*s%*s%*s%*s%s%s%*s%s%s%*s%*s%*s%*s%*s%s%s%*s%s%s%*s",s[0],t[0],s[1],t[1],s[2],t[2],s[3],t[3]);

    for(int i=0;i<4;++i) {
        double a=getang(s[i]);
        switch (t[i][0]) {
            case 'N': ang[i]=a; break;
            case 'S': ang[i]=PI-a; break;
            case 'E': ang[i]=a; break;
            case 'W': ang[i]=-a; break;
        }
    }
//  swap(ang[0],ang[1]);
//  swap(ang[2],ang[3]);
    x[0]=sin(ang[0])*cos(ang[1]), y[0]=sin(ang[0])*sin(ang[1]), z[0]=cos(ang[0]);
    x[1]=sin(ang[2])*cos(ang[3]), y[1]=sin(ang[2])*sin(ang[3]), z[1]=cos(ang[2]);
    double d=sqrt(sqr(x[1]-x[0])+sqr(y[1]-y[0])+sqr(z[1]-z[0]));

    double rad=acos((2-d*d)/2);
    printf("%.2lf\n", EarthR*rad);
}

int main(){
    freopen("in.txt","r",stdin);
    solve();
    for(;;);
    return 0;
}

URAL 1031

/*
題意:火車有三種區間票,花費Ci可以坐Li距離,然後求兩點之間最小花費
題解:因爲f[]有單調性所以直接二分一把即可。 
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

constint maxn=10010;

int n,s,t;
int L[3],C[3];
int a[maxn],f[maxn];
void solve(){
    for(int i=0;i<3;++i)scanf("%d",L+i);
    for(int i=0;i<3;++i)scanf("%d",C+i);
    scanf("%d%d%d",&n,&s,&t);
    if(s>t)swap(s,t);
    a[1]=0;
    for(int i=2;i<=n;++i)
        scanf("%d",&a[i]);

    memset(f,0x3f,sizeof f);
    for(int i=1;i<=s;++i)f[i]=0;
    for(int i=s+1;i<=t;++i){
        for(int j=0;j<3;++j){
            int x=lower_bound(a+1,a+1+n,a[i]-L[j])-a;
            if(x==i) continue;
            f[i]=min(f[i],f[x]+C[j]);
        }
    }
    printf("%d\n",f[t]);
}

int main(){
//  freopen("in.txt","r",stdin);
    solve();
//  for(;;);
    return 0;
}

URAL 1032

/*
題意,找出幾個數使和能被N整除
解法,累加對N取模,如果有相同的模表示這兩個數之間的幾個數的和被N整除
(由抽屜原理,模只有1 to N-1(0的時候單個數即可),累加結果有N個,必然存在至少一組相同的模

cao..這題竟然要輸出數,而不是數的編號。。。 
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

typedef long long LL;

const int maxn=10010;

int n;
LL a[maxn], s[maxn];
int no[maxn];
void solve(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        int x; scanf("%d",&x);
        a[i]=x;
    }
    memset(no,255,sizeof no);
    s[ no[0]=0 ] = 0;
    for(int i=1;i<=n;++i){
        if(a[i]%n==0){
            printf("1\n%d\n",a[i]);
            return;
        }
        s[i]=s[i-1]+a[i];
        int x=s[i]%n;
        if(~no[x]){
            printf("%d\n",i-no[x]);
            for(int j=no[x]+1;j<=i;++j)
                printf("%d\n",a[j]);
            return;
        }
        no[x]=i;
    }
    printf("0\n");
}

int main(){
    solve();
//  for(;;);
    return 0;
}

URAL 1033

/*
給一個迷宮圖, 牆在#的位置, 或者是迷宮圖的四周.但是左上角和右下角沒有牆.
問對於一個遊客來說, 可以看見的牆的總面積.穿過2個相鄰的牆裏面的牆是不能被看見的, 2個牆相鄰當且僅當這2個牆至少有一個角碰到.

從一個角開始4方向遍歷, 走到的所有的地方上下左右看一下有沒有牆.
注意要從2個角都跑一遍.
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

typedef long long LL;

const int maxn=50;

const int dxy[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

int n;

char mp[maxn][maxn];

bool check(int x,int y){ return 0<=x&&x<n&&0<=y&&y<n&&mp[x][y]!='#'; }

bool vis[maxn][maxn];
int res;
void dfs(int x, int y){
    vis[x][y]=1;
    for(int d=0;d<4;++d){
        int X=x+dxy[d][0],Y=y+dxy[d][1];
        if (!vis[X][Y]){
            if(check(X,Y))
                dfs(X,Y);
            else
                ++res;
        }
    }
}

void solve(){
    scanf("%d",&n);
    for(int i=0;i<n;++i)
        scanf("%s",mp[i]);
    res=0;
    memset(vis,0,sizeof vis);
    dfs(0,0); if(!vis[n-1][n-1])dfs(n-1,n-1);
    printf("%d\n",(res-4)*9);
}

int main(){
//  freopen("in.txt","r",stdin);
    solve();
//  for(;;);
    return 0;
}

URAL 1034

/*
題意:給出一個n皇后的方案,要求恰好移動三個皇后且仍不互相攻擊的方案數
題解:枚舉 每個方案判斷新的三個皇后是否相互攻擊和與之前的皇后是否相互攻擊即可
(好像寫的巨煩。。) 
*/
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

typedef long long LL;

const int maxn=60;

const int dxy[4][2]={{-1,-1},{-1,1},{1,-1},{1,1}};

int n;
int x[maxn],y[maxn];
int mp[maxn][maxn];
int per[maxn];
int p[4];

bool ok(int x,int y){return 1<=x&&x<=n&&1<=y&&y<=n; }
bool check(int x,int y){
    for(int d=0;d<4;++d)
        for(int p=1;;++p){
            int X=x+dxy[d][0]*p,Y=y+dxy[d][1]*p;
            if(ok(X,Y)){
                if(mp[X][Y]==1) return 0;
            }else
                break;
        }
    return 1;
}

void solve(){
    scanf("%d",&n);
    memset(mp,0,sizeof mp);
    for(int i=1;i<=n;++i){
        scanf("%d%d",&x[i],&y[i]);
        mp[x[i]][y[i]]=1;
    }
    int res=0;
    for(p[1]=1;p[1]<=n;++p[1])
        for(p[2]=p[1]+1;p[2]<=n;++p[2])
            for(p[3]=p[2]+1;p[3]<=n;++p[3]){
                mp[x[p[1]]][y[p[1]]]=0;
                mp[x[p[2]]][y[p[2]]]=0;
                mp[x[p[3]]][y[p[3]]]=0;
                for(int i=1;i<=3;++i)per[i]=i;
                do{
                   %2�%3spcn class="hljs-keyword">bool fg=0;
                    for(int i=1;i<=3;++i)if(per[i]==i){ fg=1;break; }
                    if(fg) continue;
                    mp[x[p[1]]][y[p[per[1]]]]=1;
                    mp[x[p[2]]][y[p[per[2]]]]=1;
                    mp[x[p[3]]][y[p[per[3]]]]=1;
                    if(check(x[p[1]],y[p[per[1]]]) && check(x[p[2]],y[p[per[2]]]) && check(x[p[3]],y[p[per[3]]])){
/*                      for(int i=1;i<=n;++i,putchar('\n'))
                            for(int j=1;j<=n;++j,putchar(' '))
                                printf("%d",mp[i][j]);
                        putchar('\n');
*/                      ++ res;
                    }
                    mp[x[p[1]]][y[p[per[1]]]]=0;
                    mp[x[p[2]]][y[p[per[2]]]]=0;
                    mp[x[p[3]]][y[p[per[3]]]]=0;
                } while(next_permutation(per+1,per+1+3));
                mp[x[p[1]]][y[p[1]]]=1;
                mp[x[p[2]]][y[p[2]]]=1;
                mp[x[p[3]]][y[p[3]]]=1;
            }
    printf("%d\n",res);
}

int main(){
//  freopen("in.txt","r",stdin);
    solve();
//  for(;;);
    return 0;
}

URAL 1035

/*
題意:給出一幅十字繡的圖案,詢問最少的穿針次數(前m*n是正面圖案,後m*n是背面圖案)
一次穿針的要求�%�C%yA0A1:線頭如果從正面穿入,那麼必然從正面穿出,而且之後便翻轉方向,即從那個位置開始反面穿針。反過來亦如此
2:線頭如果到了格點,那麼必須翻轉方向,而且只能在格點翻轉方向
3:針在不反轉方向的情況下,一次只能穿1*1的格子的對角線
(好像就這些了,其實就是平常穿針的要求=_=)

解法:這是個一筆畫問題,然而卻不好建圖
於是我們可以考慮從點的度數下手
由於不同的連通塊(圖案)之間,是無法用同一根針穿起來的,所以我們考慮一個連通塊時候的情況,之後再將答案相加
對某個點,定義針需要從正面穿入穿出的爲入度,從反面穿入穿出的爲出度
那麼在一個連通圖中,一個點對度數的貢獻就是入度和出度之差的絕對值
一個連通塊對答案的貢獻就是所有點的度數貢獻之和除以2,如果之和爲0的話那麼貢獻就是1.
*/

#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

typedef long long LL;

const int maxn=210;

char mp0[maxn][maxn];
int mp[maxn][maxn], fg[maxn][maxn];
int n,m;

void read(int v){
    for(int i=0;i<n;++i)
        for(int j=0;j<m;++j){
            char x; scanf(" %c",&x);

            if(mp0[i][j]=='.') mp0[i][j]=x;
            else if((mp0[i][j]=='/' && (x=='\\' || x=='X')) || (mp0[i][j]=='\\' && (x=='/' || x=='X')))
                mp0[i][j]='X';

            if(x=='\\'||x=='X'){
                mp[i][j]+=v; mp[i+1][j+1]+=v; fg[i][j]=fg[i+1][j+1]=1;
            }
            if(x=='/'||x=='X'){
                mp[i][j+1]+=v; mp[i+1][j]+=v; fg[i][j+1]=fg[i+1][j]=1;
            }
        }

}

const int dxy[4][2]={{1,-1},{-1,1},{1,1},{-1,-1}};

bool check0(int x,int y){ return 0<=x&&x<n&&0<=y&&y<m; }
bool check(int x,int y){ return 0<=x&&x<=n&&0<=y&&y<=m; }

int s;
bool dfs(int x,int y){
    s+=abs(mp[x][y]);
//  printf("%d %d %d\n",x,y,s);
    fg[x][y]=0;

    if(check0(x,y-1) && (mp0[x][y-1]=='/'||mp0[x][y-1]=='X')){
        int d=0;
        int X=x+dxy[d][0], Y=y+dxy[d][1];
        if(check(X,Y) && fg[X][Y])
            dfs(X,Y);
    }
    if(check0(x-1,y) && (mp0[x-1][y]=='/'||mp0[x-1][y]=='X')){
        int d=1;
        int X=x+dxy[d][0], Y=y+dxy[d][1];
        if(check(X,Y) && fg[X][Y])
            dfs(X,Y);
    }
    if(check0(x,y) && (mp0[x][y]=='\\'||mp0[x][y]=='X')){
        int d=2;
        int X=x+dxy[d][0], Y=y+dxy[d][1];
        if(check(X,Y) && fg[X][Y])
            dfs(X,Y);
    }
    if(check0(x-1,y-1) && (mp0[x-1][y-1]=='\\'||mp0[x-1][y-1]=='X')){
        int d=3;
        int X=x+dxy[d][0], Y=y+dxy[d][1];
        if(check(X,Y) && fg[X][Y])
            dfs(X,Y);
    }
}

void solve(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i) for(int j=0;j<m;++j) mp0[i][j]='.';
    read(1); read(-1);
    int res=0;
    for(int i=0;i<=n;++i)
        for(int j=0;j<=m;++j)if(fg[i][j]){
            s=0;
            dfs(i,j);
            s=s/2;
//          printf("%d %d %d\n===========\n",i,j,s);
            res+=(s==0?1:s);
        }
    printf("%d\n",res);
}

int main(){
//  freopen("in.txt","r",stdin);
    solve();
//  for(;;);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章