顯示具有 TOI入營考 標籤的文章。 顯示所有文章
顯示具有 TOI入營考 標籤的文章。 顯示所有文章

2016年3月3日 星期四

(Zj) a454: TOI2010 第二題:專案時程

http://zerojudge.tw/ShowProblem?problemid=a454

先存有多少入度(指向自己),出度(指向別人)

然後瘋狂對入度=0做bfs,然後認真dp一番,就OK了。

#include <iostream>
#include <stdio.h>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

const int MAX_N = 1003;
const int INF = 475634765;

int rudu[MAX_N];
int dp[MAX_N];
int pre_max[MAX_N];
bool visit[MAX_N];
bool in_que[MAX_N];
vector<int> chudu[MAX_N];
queue<int> que;

void bfs(int root) {
    int ret=-1;
    visit[root]=true;
    que.push(root);
    while (!que.empty()) {
        int tmp=que.front();
        que.pop();
        dp[tmp]+=pre_max[tmp];
        in_que[tmp]=false;
        visit[tmp]=true;
        int len=chudu[tmp].size();
        for (int x=0;len>x;x++) {
            int y=chudu[tmp][x];
            pre_max[y]=max(pre_max[y],dp[tmp]);
            rudu[y]--;
            if (rudu[y]==0) {
                if (in_que[y]==false) {
                    que.push(y);
                    in_que[y]=true;
                }
            }
        }
    }
}

int main () {
    int T;
    scanf("%d",&T);
    while (T--) {
        memset(rudu,0,sizeof(rudu));//入度 
        memset(dp,0,sizeof(dp));    //cost
        memset(pre_max,0,sizeof(pre_max));
        int n;
        scanf("%d",&n);
        for (int x=1;n>=x;x++) {
            scanf("%d",&dp[x]);
            chudu[x].clear();
            visit[x]=false;
            int i;
            scanf("%d",&i);
            for (int y=0;i>y;y++) {
                int k;
                scanf("%d",&k);
                rudu[k]++;
                chudu[x].push_back(k);
            }
        }
        int ans=-INF;
        for (int i=1;n>=i;i++) {
            if (visit[i]==false && rudu[i]==0) bfs(i);
        }
        for (int i=1;n>=i;i++) {
            ans=max(ans,dp[i]);
        }
        printf("%d\n",ans);
    }
}

(Zj) a074: TOI2011 第五題:畫作問題

http://zerojudge.tw/ShowProblem?problemid=a074

一開始完全不知如何下手

後來就想想,一個三角形,要先有三條線,這三條線互相交錯的解答不能是無解(兩條線平行)或相同(三線共點),有了這三條線後,再判斷其他的線會不會交在這個三角形上面,就OK了。

(後記) 認真研究複雜度,發現實際上的複雜度為 O(4 * (k/4)^3 * k) = O(k^4),以k=296的情況來看,應該不會過啊~


#include <iostream>
#include <stdio.h>
#include <assert.h>
using namespace std;

const int MAX_K = 310;
const int INF = 32434259;
int n,m,k;

struct Node {
    double x;
    double y;
    bool real;   //really have answer ???
    bool same;   //the same???
};
//y=ax+b
double a[MAX_K],b[MAX_K];  //yi=aix+bi
Node ans[MAX_K][MAX_K];  //yi=aix+bi 和 yj=ajx+bj 的解 

Node get_ans(int i,int j) {
    Node ret;
    if (i==j) {
        ret.real=false;
        ret.same=false;
    }
    else {
        if (a[i]==a[j]&&b[i]==b[j]) {     //一樣直線 
            ret.real=false;
            ret.same=true;
        }
        else if (a[i]==a[j]&&b[i]!=b[j]) { //斜率一樣but  y潔具不同 
            ret.real=false;
            ret.same=false;
        }
        else if (a[i]==INF) {   //x=???
            ret.x=b[i];
            ret.y=a[j]*b[i]+b[j];
            ret.real=true;
            ret.same=true;
        }
        else if (a[j]==INF) { //x=???
            ret.x=b[j];
            ret.y=a[i]*b[j]+b[i];
            ret.real=true;
            ret.same=true;
        }
        else {
            ret.x=(b[i]-b[j])/(a[j]-a[i]);
            ret.y=a[i]*ret.x+b[i];
            assert(ret.y==a[j]*ret.x+b[j]);
            ret.real=true;
            ret.same=true;
        }
    }
    return ret;
}

void fill_ans(int k) {
    k+=4;
    for (int x=0;k>x;x++) {
        for (int y=0;k>y;y++) {
            ans[x][y]=get_ans(x,y);
        }
    }
}

bool in_range(Node node,double x1,double y1,double x2,double y2) {
    if (x1>x2)swap(x1,x2);
    if (y1>y2)swap(y1,y2);
    if (node.x<x1) return false;
    if (node.x>x2) return false;
    if (node.y<y1) return false;
    if (node.y>y2) return false;
    return true;
}

bool in_range2(Node node,double x1,double y1,double x2,double y2) {
    if (x1>x2)swap(x1,x2);
    if (y1>y2)swap(y1,y2);
    if (node.x<x1) return false;
    if (node.x>x2) return false;
    if (node.y<y1) return false;
    if (node.y>y2) return false;
    return true;
}

bool operator==(const Node& n1, const Node& n2) {
    return (n1.x==n2.x&&n2.y==n1.y);
}

bool check_line(Node node1, Node node2,int i,int k) {
    double x1=node1.x;
    double x2=node2.x;
    double y1=node1.y;
    double y2=node2.y;
    for (int x=0;k>x;x++) {
        if (ans[i][x].real==true) {
            if (ans[i][x]==node1||ans[i][x]==node2) {

            }
            if (ans[i][x]==node1||ans[i][x]==node2) continue;
            if (in_range2(ans[i][x],x1,y1,x2,y2)==true) {

                return false;
            }
        }
    }
    return true;
}

int main () {
    while (scanf("%d %d %d",&n,&m,&k) != EOF) {
        for (int x=0;k>x;x++) {
            int x1,x2,y1,y2;
            scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
            if (x1==x2) {  //鉛直縣 
                a[x]=INF;
                b[x]=x1;
            }
            else if (y1==y2) {  //水平線 
                a[x]=0;
                b[x]=y1;
            }
            else {
                a[x]=(y2-y1)/(x2-x1);
                assert(x2-x1!=0);
                b[x]=y2-x2*a[x];
                assert(b[x]==(y1-a[x]*x1));
            }
        }
        //端點 
        a[k]=INF;
        b[k]=0;
        a[k+1]=0;
        b[k+1]=0;
        a[k+2]=INF;
        b[k+2]=n;
        a[k+3]=0;
        b[k+3]=m;
        fill_ans(k);
        k+=4;
        int anss=0;
        for (int p=0;k>p;p++) {
            for (int q=p+1;k>q;q++) {
                Node node[3];
                node[0]=ans[p][q];
                if (node[0].real==false) continue;
                for (int r=q+1;k>r;r++) {   //枚舉which三條作出的三角形 

                    node[0]=ans[p][q];
                    node[1]=ans[p][r];
                    node[2]=ans[q][r];
                    bool check=false;
                    for (int s=0;3>s;s++) {

                        if (node[s].real==false) check=true;
                        else if (in_range(node[s],0,0,n,m)!=true) check=true;
                    }

                    if (check==true) continue;
                    if (node[0]==node[1]) continue;
                    
                    check=check_line(node[0],node[1],p,k);
                    if (check==false) continue;
                    check=check_line(node[1],node[2],r,k);
                    if (check==false) continue;
                    check=check_line(node[0],node[2],q,k);
                    if (check==false) continue;
                    
                    anss++;
                }
            }
        }
        printf("%d\n",anss);
    }
}