NOJ AC75记录

NOJ刷题总结

+++

HDU2553

可能因为样例过多的缘故,刚开始疯狂TLE,后来就需要打表过。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 20;
char g[N][N];
bool bias1[N], bias2[N], col[N];
int sum;
int storage[10];//打表

void dfs(int u, int n)
{
    if(u == n)
    {
        sum++;
        return;
    }
    for(int i = 0; i < n; i++ )
        if(!col[i] && !bias1[u + i] & !bias2[n - u + i])
        {
            col[i] = bias1[u + i] = bias2[n - u + i] = true;
            dfs(u + 1, n);
            col[i] = bias1[u + i] = bias2[n - u + i] = false;
        }
}

int main()
{
    for(int i = 0; i < 10; i++ )
    {
        sum = 0;
        dfs(0, i + 1);
        storage[i] = sum;
    }
    
    int u;
    while(cin >> u, u)
        cout << storage[u - 1] << endl;   
    return 0;
}
NOJ1049 飞机航班求最短路
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 25;
int n, m, v;
int h[N], e[N], ne[N], q[N], d[N], idx;

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void bfs()
{
    int hh = 0, tt = 0;
    q[0] = v;
    memset(d, -1, sizeof d);
    
    d[v] = 0;
    while(hh <= tt)
    {
        int t = q[hh++];
        
        for(int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if(d[j] == -1)
            {
                d[j] = d[t] + 1;
                q[++tt] = j;
            }
        }
    }
    
    for(int i = 0; i < n; i++ )
    {
        if(i == v) continue;
        cout << d[i] << endl;    
    }
}

int main()
{
    cin >> n >> m >> v;
    memset(h, -1, sizeof h);
    
    for(int i = 0; i < m; i++ )
    {
        int x, y;
        cin >> x >> y;
        add(x, y);
    }
    
    bfs();
    
    return 0;
}
NOJ1079 11111...

既然枚举n的倍数复杂度过高,就反过来枚举不同位数的1

#include <cstdio>
 
int main()
{
	int n;
	while(~scanf("%I64d", &n))
	{
		int t = 0, ans = 0;
		while(true)
		{
			t = (10 * t + 1) % n;
			ans++;
			if(0 == t) break;
		}
		printf("%d
", ans);
	}
	return 0;
}
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100010;

int n, m;
int h[N], cnt;

void down(int u)
{
    int t = u;
    if (u * 2 <= cnt && h[u * 2] < h[t]) t = u * 2;
    if (u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
    if (u != t)
    {
        swap(h[u], h[t]);
        down(t);
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &h[i]);
    cnt = n;

    for (int i = n / 2; i; i -- ) down(i);

    while (m -- )
    {
        printf("%d ", h[1]);
        h[1] = h[cnt -- ];
        down(1);
    }

    puts("");

    return 0;
}
HDU2546 饭卡

果然自己做出一道dp题是很开心的一件事,(虽然是和模板01背包几乎一样)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1010;
int w[N], m, n, g[N][N];

int main()
{
    while(cin >> m, m)
    {
        for(int i = 1; i <= m; i ++ ) cin >> w[i];
        cin >> n;
        
        if(n < 5)
            cout << n << endl;
        else
        {
        sort(w + 1, w + m + 1);
        
        for(int i = 1; i < m; i ++ )
            for(int j = 0; j <= n - 5; j ++ )
            {
                g[i][j] = g[i - 1][j];
                if(j >= w[i]) g[i][j] = max(g[i][j], g[i - 1][j - w[i]] + w[i]);
            }
        
        cout << n - g[m - 1][n - 5] - w[m] << endl;
        }
    }
    return 0;
}
VIJ1360 八数码

记录初次使用哈希表

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#include <queue>

using namespace std;


int bfs(string s)
{
    queue<string> q;
    unordered_map<string, int> d;
    
    q.push(s);
    d[s] = 0;
    
    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
    string end = "123804765";
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        
        if(t == end) return d[t];
        
        int distence = d[t];
        int k = t.find('0');
        int x = k / 3, y = k % 3;
        for(int i = 0; i < 4; i ++ )
        {
            int a = x + dx[i], b = y + dy[i];
            if(a >= 0 && a < 3 && b >= 0 && b < 3)
            {
                swap(t[a * 3 + b], t[k]);
                if(!d.count(t))
                {
                    d[t] = distence + 1;
                    q.push(t);
                }
                swap(t[k], t[a * 3 + b]);
            }
        }
    }
}

int main()
{
    string s;
    cin >> s;
    
    cout << bfs(s) << endl;
    
    return 0;
}
HDU2036 给点坐标求面积

多边形的面积可以转换为若干个三角形面积的相加,三角形顶点是最后一个点

三角形的有向面积计算公式:

s = (x2y3+x3y1+x1y2-x2y1-x3y2-x1y3)/2.0

#include <iostream>

using namespace std;

int n,x1,y1,x2,y2,x3,y3;  
double s;  

double getArea(int x1,int y1,int x2,int y2,int x3,int y3)  
{  
    return (x2*y3+x3*y1+x1*y2-x2*y1-x3*y2-x1*y3)/2.0;  
}  

int main(){  
    while(~scanf("%d",&n))  
    {  
        if(!n)break;  
        s = 0;  
        scanf("%d %d %d %d %d %d",&x1,&y1,&x2,&y2,&x3,&y3);  
        s += getArea(x1,y1,x2,y2,x3,y3);  
        n = n-3;  
        while(n>0){  
            n--;  
            x2 = x3;  
            y2 = y3;  
            scanf("%d%d",&x3,&y3);  
            s += getArea(x1,y1,x2,y2,x3,y3);  
        }  
        printf("%.1f
",s);  
    }  
    return 0;  
}  
HDU2048 神,上帝与老天爷 (典型错排dp)

1.假设n个人,前n - 1 个人满足错排,那么第n个人与前面任意一个人互换就可以,一共有(n - 1) * f(n - 1)种情况。

2.假设n个人,前n - 1不满足错排,然后第n个人与其中一个人互换后满足错排。也就是说前n - 2个人满足错排,因为每个人都可以是之前不满足错排的原因,所以这种情况一共有(n - 1) * f(n - 2)种。

综上列出状态转移方程f(n) = (n - 1) * (f(n - 1) + f(n - 2))

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 30;
double num[N], sum[N];

void chart()
{
    num[1] = 0, num[2] = 1;
    sum[1] = 1, sum[2] = 2;
    
    for(int i = 3; i < 25; i ++ )
    {
        num[i] = (i - 1) * (num[i - 1] + num[i - 2]), sum[i] = sum[i - 1] * i;
    }
}

int main()
{
    int t;
    cin >> t;
    
    chart();
    
    while(t--)
    {
        int n;
        cin >> n;
        printf("%.2lf%%
", (num[n] / sum[n]) * 100.0);
    }
    return 0;
}
HDU2049 错排
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long LL;

int main()
{
    int n, m, c;
    LL sum[21], f[21];
    
    sum[0] = 1, sum[1] = 1;
    f[0] = 1, f[1] = 0;
    
    for(int i = 2; i < 21;i ++ )
    {
        sum[i] = sum[i-1] * i;
        f[i] = (i-1)*(f[i-1] + f[i-2]);
    }
    
    cin>>c;
    for(int j = 0; j < c;j ++ )
    {
        cin>>n >> m;
        cout << f[m] * (sum[n] / sum[m] /sum[n-m]) << endl;
    }
    
    return 0;
}
HDU2045 简单递推

数据n = 3比较卡,要单独赋值。

#include <iostream>

using namespace std;

typedef long long LL;

const int N = 55;
LL dp[N];

void chart()
{
    dp[1] = 3, dp[2] = 6, dp[3] = 6;
    
    for(int i = 4; i <= 50; i ++ )
        dp[i] = dp[i - 1] + 2 * dp[i - 2];
}

int main()
{
    chart();
    
    int n;
    while(cin >> n)
        cout << dp[n] << endl;
    
    return 0;
}
原文地址:https://www.cnblogs.com/scl0725/p/12612430.html